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.3.6
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/* Disable security warnings for BSD sockets on MSVC */
24#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
25# define _CRT_SECURE_NO_WARNINGS
26#endif
27
28#include "open62541.h"
29
30/**** amalgamated original file "/deps/open62541_queue.h" ****/
31
32/* $OpenBSD: queue.h,v 1.38 2013/07/03 15:05:21 fgsch Exp $ */
33/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
34
35/*
36 * Copyright (c) 1991, 1993
37 * The Regents of the University of California. All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)queue.h 8.5 (Berkeley) 8/20/94
64 */
65
66
67/*
68 * This file defines five types of data structures: singly-linked lists,
69 * lists, simple queues, tail queues, and circular queues.
70 *
71 *
72 * A singly-linked list is headed by a single forward pointer. The elements
73 * are singly linked for minimum space and pointer manipulation overhead at
74 * the expense of O(n) removal for arbitrary elements. New elements can be
75 * added to the list after an existing element or at the head of the list.
76 * Elements being removed from the head of the list should use the explicit
77 * macro for this purpose for optimum efficiency. A singly-linked list may
78 * only be traversed in the forward direction. Singly-linked lists are ideal
79 * for applications with large datasets and few or no removals or for
80 * implementing a LIFO queue.
81 *
82 * A list is headed by a single forward pointer (or an array of forward
83 * pointers for a hash table header). The elements are doubly linked
84 * so that an arbitrary element can be removed without a need to
85 * traverse the list. New elements can be added to the list before
86 * or after an existing element or at the head of the list. A list
87 * may only be traversed in the forward direction.
88 *
89 * A simple queue is headed by a pair of pointers, one the head of the
90 * list and the other to the tail of the list. The elements are singly
91 * linked to save space, so elements can only be removed from the
92 * head of the list. New elements can be added to the list before or after
93 * an existing element, at the head of the list, or at the end of the
94 * list. A simple queue may only be traversed in the forward direction.
95 *
96 * A tail queue is headed by a pair of pointers, one to the head of the
97 * list and the other to the tail of the list. The elements are doubly
98 * linked so that an arbitrary element can be removed without a need to
99 * traverse the list. New elements can be added to the list before or
100 * after an existing element, at the head of the list, or at the end of
101 * the list. A tail queue may be traversed in either direction.
102 *
103 * A circle queue is headed by a pair of pointers, one to the head of the
104 * list and the other to the tail of the list. The elements are doubly
105 * linked so that an arbitrary element can be removed without a need to
106 * traverse the list. New elements can be added to the list before or after
107 * an existing element, at the head of the list, or at the end of the list.
108 * A circle queue may be traversed in either direction, but has a more
109 * complex end of list detection.
110 *
111 * For details on the use of these macros, see the queue(3) manual page.
112 */
113
114#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
115#define _Q_INVALIDATE(a) (a) = ((void *)-1)
116#else
117#define _Q_INVALIDATE(a)
118#endif
119
120/*
121 * Singly-linked List definitions.
122 */
123#define SLIST_HEAD(name, type) \
124struct name { \
125 struct type *slh_first; /* first element */ \
126}
127
128#define SLIST_HEAD_INITIALIZER(head) \
129 { NULL }
130
131#define SLIST_ENTRY(type) \
132struct { \
133 struct type *sle_next; /* next element */ \
134}
135
136/*
137 * Singly-linked List access methods.
138 */
139#define SLIST_FIRST(head) ((head)->slh_first)
140#define SLIST_END(head) NULL
141#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
142#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
143
144#define SLIST_FOREACH(var, head, field) \
145 for((var) = SLIST_FIRST(head); \
146 (var) != SLIST_END(head); \
147 (var) = SLIST_NEXT(var, field))
148
149#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
150 for ((var) = SLIST_FIRST(head); \
151 (var) && ((tvar) = SLIST_NEXT(var, field), 1); \
152 (var) = (tvar))
153
154/*
155 * Singly-linked List functions.
156 */
157#define SLIST_INIT(head) do { \
158 SLIST_FIRST(head) = SLIST_END(head); \
159} while(0)
160
161#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
162 (elm)->field.sle_next = (slistelm)->field.sle_next; \
163 (slistelm)->field.sle_next = (elm); \
164} while (0)
165
166#define SLIST_INSERT_HEAD(head, elm, field) do { \
167 (elm)->field.sle_next = (head)->slh_first; \
168 (head)->slh_first = (elm); \
169} while (0)
170
171#define SLIST_REMOVE_AFTER(elm, field) do { \
172 (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
173} while (0)
174
175#define SLIST_REMOVE_HEAD(head, field) do { \
176 (head)->slh_first = (head)->slh_first->field.sle_next; \
177} while (0)
178
179#define SLIST_REMOVE(head, elm, type, field) do { \
180 if ((head)->slh_first == (elm)) { \
181 SLIST_REMOVE_HEAD((head), field); \
182 } else { \
183 struct type *curelm = (head)->slh_first; \
184 \
185 while (curelm->field.sle_next != (elm)) \
186 curelm = curelm->field.sle_next; \
187 curelm->field.sle_next = \
188 curelm->field.sle_next->field.sle_next; \
189 _Q_INVALIDATE((elm)->field.sle_next); \
190 } \
191} while (0)
192
193/*
194 * List definitions.
195 */
196#define LIST_HEAD(name, type) \
197struct name { \
198 struct type *lh_first; /* first element */ \
199}
200
201#define LIST_HEAD_INITIALIZER(head) \
202 { NULL }
203
204#define LIST_ENTRY(type) \
205struct { \
206 struct type *le_next; /* next element */ \
207 struct type **le_prev; /* address of previous next element */ \
208}
209
210/*
211 * List access methods
212 */
213#define LIST_FIRST(head) ((head)->lh_first)
214#define LIST_END(head) NULL
215#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
216#define LIST_NEXT(elm, field) ((elm)->field.le_next)
217
218#define LIST_FOREACH(var, head, field) \
219 for((var) = LIST_FIRST(head); \
220 (var)!= LIST_END(head); \
221 (var) = LIST_NEXT(var, field))
222
223#define LIST_FOREACH_SAFE(var, head, field, tvar) \
224 for ((var) = LIST_FIRST(head); \
225 (var) && ((tvar) = LIST_NEXT(var, field), 1); \
226 (var) = (tvar))
227
228/*
229 * List functions.
230 */
231#define LIST_INIT(head) do { \
232 LIST_FIRST(head) = LIST_END(head); \
233} while (0)
234
235#define LIST_INSERT_AFTER(listelm, elm, field) do { \
236 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
237 (listelm)->field.le_next->field.le_prev = \
238 &(elm)->field.le_next; \
239 (listelm)->field.le_next = (elm); \
240 (elm)->field.le_prev = &(listelm)->field.le_next; \
241} while (0)
242
243#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
244 (elm)->field.le_prev = (listelm)->field.le_prev; \
245 (elm)->field.le_next = (listelm); \
246 *(listelm)->field.le_prev = (elm); \
247 (listelm)->field.le_prev = &(elm)->field.le_next; \
248} while (0)
249
250#define LIST_INSERT_HEAD(head, elm, field) do { \
251 if (((elm)->field.le_next = (head)->lh_first) != NULL) \
252 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
253 (head)->lh_first = (elm); \
254 (elm)->field.le_prev = &(head)->lh_first; \
255} while (0)
256
257#define LIST_REMOVE(elm, field) do { \
258 if ((elm)->field.le_next != NULL) \
259 (elm)->field.le_next->field.le_prev = \
260 (elm)->field.le_prev; \
261 *(elm)->field.le_prev = (elm)->field.le_next; \
262 _Q_INVALIDATE((elm)->field.le_prev); \
263 _Q_INVALIDATE((elm)->field.le_next); \
264} while (0)
265
266#define LIST_REPLACE(elm, elm2, field) do { \
267 if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
268 (elm2)->field.le_next->field.le_prev = \
269 &(elm2)->field.le_next; \
270 (elm2)->field.le_prev = (elm)->field.le_prev; \
271 *(elm2)->field.le_prev = (elm2); \
272 _Q_INVALIDATE((elm)->field.le_prev); \
273 _Q_INVALIDATE((elm)->field.le_next); \
274} while (0)
275
276/*
277 * Simple queue definitions.
278 */
279#define SIMPLEQ_HEAD(name, type) \
280struct name { \
281 struct type *sqh_first; /* first element */ \
282 struct type **sqh_last; /* addr of last next element */ \
283}
284
285#define SIMPLEQ_HEAD_INITIALIZER(head) \
286 { NULL, &(head).sqh_first }
287
288#define SIMPLEQ_ENTRY(type) \
289struct { \
290 struct type *sqe_next; /* next element */ \
291}
292
293/*
294 * Simple queue access methods.
295 */
296#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
297#define SIMPLEQ_END(head) NULL
298#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
299#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
300
301#define SIMPLEQ_FOREACH(var, head, field) \
302 for((var) = SIMPLEQ_FIRST(head); \
303 (var) != SIMPLEQ_END(head); \
304 (var) = SIMPLEQ_NEXT(var, field))
305
306#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
307 for ((var) = SIMPLEQ_FIRST(head); \
308 (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
309 (var) = (tvar))
310
311/*
312 * Simple queue functions.
313 */
314#define SIMPLEQ_INIT(head) do { \
315 (head)->sqh_first = NULL; \
316 (head)->sqh_last = &(head)->sqh_first; \
317} while (0)
318
319#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
320 if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
321 (head)->sqh_last = &(elm)->field.sqe_next; \
322 (head)->sqh_first = (elm); \
323} while (0)
324
325#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
326 (elm)->field.sqe_next = NULL; \
327 *(head)->sqh_last = (elm); \
328 (head)->sqh_last = &(elm)->field.sqe_next; \
329} while (0)
330
331#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
332 if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
333 (head)->sqh_last = &(elm)->field.sqe_next; \
334 (listelm)->field.sqe_next = (elm); \
335} while (0)
336
337#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
338 if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
339 (head)->sqh_last = &(head)->sqh_first; \
340} while (0)
341
342#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
343 if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
344 == NULL) \
345 (head)->sqh_last = &(elm)->field.sqe_next; \
346} while (0)
347
348/*
349 * XOR Simple queue definitions.
350 */
351#define XSIMPLEQ_HEAD(name, type) \
352struct name { \
353 struct type *sqx_first; /* first element */ \
354 struct type **sqx_last; /* addr of last next element */ \
355 unsigned long sqx_cookie; \
356}
357
358#define XSIMPLEQ_ENTRY(type) \
359struct { \
360 struct type *sqx_next; /* next element */ \
361}
362
363/*
364 * XOR Simple queue access methods.
365 */
366#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \
367 (unsigned long)(ptr)))
368#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first))
369#define XSIMPLEQ_END(head) NULL
370#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
371#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
372
373
374#define XSIMPLEQ_FOREACH(var, head, field) \
375 for ((var) = XSIMPLEQ_FIRST(head); \
376 (var) != XSIMPLEQ_END(head); \
377 (var) = XSIMPLEQ_NEXT(head, var, field))
378
379#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
380 for ((var) = XSIMPLEQ_FIRST(head); \
381 (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
382 (var) = (tvar))
383
384/*
385 * XOR Simple queue functions.
386 */
387#define XSIMPLEQ_INIT(head) do { \
388 arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
389 (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \
390 (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
391} while (0)
392
393#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
394 if (((elm)->field.sqx_next = (head)->sqx_first) == \
395 XSIMPLEQ_XOR(head, NULL)) \
396 (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
397 (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \
398} while (0)
399
400#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
401 (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \
402 *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
403 (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
404} while (0)
405
406#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
407 if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \
408 XSIMPLEQ_XOR(head, NULL)) \
409 (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
410 (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \
411} while (0)
412
413#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \
414 if (((head)->sqx_first = XSIMPLEQ_XOR(head, \
415 (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
416 (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
417} while (0)
418
419#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
420 if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \
421 (elm)->field.sqx_next)->field.sqx_next) \
422 == XSIMPLEQ_XOR(head, NULL)) \
423 (head)->sqx_last = \
424 XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
425} while (0)
426
427
428/*
429 * Tail queue definitions.
430 */
431#define TAILQ_HEAD(name, type) \
432struct name { \
433 struct type *tqh_first; /* first element */ \
434 struct type **tqh_last; /* addr of last next element */ \
435}
436
437#define TAILQ_HEAD_INITIALIZER(head) \
438 { NULL, &(head).tqh_first }
439
440#define TAILQ_ENTRY(type) \
441struct { \
442 struct type *tqe_next; /* next element */ \
443 struct type **tqe_prev; /* address of previous next element */ \
444}
445
446/*
447 * tail queue access methods
448 */
449#define TAILQ_FIRST(head) ((head)->tqh_first)
450#define TAILQ_END(head) NULL
451#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
452#define TAILQ_LAST(head, headname) \
453 (*(((struct headname *)((head)->tqh_last))->tqh_last))
454/* XXX */
455#define TAILQ_PREV(elm, headname, field) \
456 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
457#define TAILQ_EMPTY(head) \
458 (TAILQ_FIRST(head) == TAILQ_END(head))
459
460#define TAILQ_FOREACH(var, head, field) \
461 for((var) = TAILQ_FIRST(head); \
462 (var) != TAILQ_END(head); \
463 (var) = TAILQ_NEXT(var, field))
464
465#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
466 for ((var) = TAILQ_FIRST(head); \
467 (var) != TAILQ_END(head) && \
468 ((tvar) = TAILQ_NEXT(var, field), 1); \
469 (var) = (tvar))
470
471
472#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
473 for((var) = TAILQ_LAST(head, headname); \
474 (var) != TAILQ_END(head); \
475 (var) = TAILQ_PREV(var, headname, field))
476
477#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
478 for ((var) = TAILQ_LAST(head, headname); \
479 (var) != TAILQ_END(head) && \
480 ((tvar) = TAILQ_PREV(var, headname, field), 1); \
481 (var) = (tvar))
482
483/*
484 * Tail queue functions.
485 */
486#define TAILQ_INIT(head) do { \
487 (head)->tqh_first = NULL; \
488 (head)->tqh_last = &(head)->tqh_first; \
489} while (0)
490
491#define TAILQ_INSERT_HEAD(head, elm, field) do { \
492 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
493 (head)->tqh_first->field.tqe_prev = \
494 &(elm)->field.tqe_next; \
495 else \
496 (head)->tqh_last = &(elm)->field.tqe_next; \
497 (head)->tqh_first = (elm); \
498 (elm)->field.tqe_prev = &(head)->tqh_first; \
499} while (0)
500
501#define TAILQ_INSERT_TAIL(head, elm, field) do { \
502 (elm)->field.tqe_next = NULL; \
503 (elm)->field.tqe_prev = (head)->tqh_last; \
504 *(head)->tqh_last = (elm); \
505 (head)->tqh_last = &(elm)->field.tqe_next; \
506} while (0)
507
508#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
509 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
510 (elm)->field.tqe_next->field.tqe_prev = \
511 &(elm)->field.tqe_next; \
512 else \
513 (head)->tqh_last = &(elm)->field.tqe_next; \
514 (listelm)->field.tqe_next = (elm); \
515 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
516} while (0)
517
518#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
519 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
520 (elm)->field.tqe_next = (listelm); \
521 *(listelm)->field.tqe_prev = (elm); \
522 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
523} while (0)
524
525#define TAILQ_REMOVE(head, elm, field) do { \
526 if (((elm)->field.tqe_next) != NULL) \
527 (elm)->field.tqe_next->field.tqe_prev = \
528 (elm)->field.tqe_prev; \
529 else \
530 (head)->tqh_last = (elm)->field.tqe_prev; \
531 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
532 _Q_INVALIDATE((elm)->field.tqe_prev); \
533 _Q_INVALIDATE((elm)->field.tqe_next); \
534} while (0)
535
536#define TAILQ_REPLACE(head, elm, elm2, field) do { \
537 if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
538 (elm2)->field.tqe_next->field.tqe_prev = \
539 &(elm2)->field.tqe_next; \
540 else \
541 (head)->tqh_last = &(elm2)->field.tqe_next; \
542 (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
543 *(elm2)->field.tqe_prev = (elm2); \
544 _Q_INVALIDATE((elm)->field.tqe_prev); \
545 _Q_INVALIDATE((elm)->field.tqe_next); \
546} while (0)
547
548/*
549 * Circular queue definitions.
550 */
551#define CIRCLEQ_HEAD(name, type) \
552struct name { \
553 struct type *cqh_first; /* first element */ \
554 struct type *cqh_last; /* last element */ \
555}
556
557#define CIRCLEQ_HEAD_INITIALIZER(head) \
558 { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
559
560#define CIRCLEQ_ENTRY(type) \
561struct { \
562 struct type *cqe_next; /* next element */ \
563 struct type *cqe_prev; /* previous element */ \
564}
565
566/*
567 * Circular queue access methods
568 */
569#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
570#define CIRCLEQ_LAST(head) ((head)->cqh_last)
571#define CIRCLEQ_END(head) ((void *)(head))
572#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
573#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
574#define CIRCLEQ_EMPTY(head) \
575 (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
576
577#define CIRCLEQ_FOREACH(var, head, field) \
578 for((var) = CIRCLEQ_FIRST(head); \
579 (var) != CIRCLEQ_END(head); \
580 (var) = CIRCLEQ_NEXT(var, field))
581
582#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \
583 for ((var) = CIRCLEQ_FIRST(head); \
584 (var) != CIRCLEQ_END(head) && \
585 ((tvar) = CIRCLEQ_NEXT(var, field), 1); \
586 (var) = (tvar))
587
588#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
589 for((var) = CIRCLEQ_LAST(head); \
590 (var) != CIRCLEQ_END(head); \
591 (var) = CIRCLEQ_PREV(var, field))
592
593#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
594 for ((var) = CIRCLEQ_LAST(head, headname); \
595 (var) != CIRCLEQ_END(head) && \
596 ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \
597 (var) = (tvar))
598
599/*
600 * Circular queue functions.
601 */
602#define CIRCLEQ_INIT(head) do { \
603 (head)->cqh_first = CIRCLEQ_END(head); \
604 (head)->cqh_last = CIRCLEQ_END(head); \
605} while (0)
606
607#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
608 (elm)->field.cqe_next = (listelm)->field.cqe_next; \
609 (elm)->field.cqe_prev = (listelm); \
610 if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
611 (head)->cqh_last = (elm); \
612 else \
613 (listelm)->field.cqe_next->field.cqe_prev = (elm); \
614 (listelm)->field.cqe_next = (elm); \
615} while (0)
616
617#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
618 (elm)->field.cqe_next = (listelm); \
619 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
620 if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
621 (head)->cqh_first = (elm); \
622 else \
623 (listelm)->field.cqe_prev->field.cqe_next = (elm); \
624 (listelm)->field.cqe_prev = (elm); \
625} while (0)
626
627#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
628 (elm)->field.cqe_next = (head)->cqh_first; \
629 (elm)->field.cqe_prev = CIRCLEQ_END(head); \
630 if ((head)->cqh_last == CIRCLEQ_END(head)) \
631 (head)->cqh_last = (elm); \
632 else \
633 (head)->cqh_first->field.cqe_prev = (elm); \
634 (head)->cqh_first = (elm); \
635} while (0)
636
637#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
638 (elm)->field.cqe_next = CIRCLEQ_END(head); \
639 (elm)->field.cqe_prev = (head)->cqh_last; \
640 if ((head)->cqh_first == CIRCLEQ_END(head)) \
641 (head)->cqh_first = (elm); \
642 else \
643 (head)->cqh_last->field.cqe_next = (elm); \
644 (head)->cqh_last = (elm); \
645} while (0)
646
647#define CIRCLEQ_REMOVE(head, elm, field) do { \
648 if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
649 (head)->cqh_last = (elm)->field.cqe_prev; \
650 else \
651 (elm)->field.cqe_next->field.cqe_prev = \
652 (elm)->field.cqe_prev; \
653 if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
654 (head)->cqh_first = (elm)->field.cqe_next; \
655 else \
656 (elm)->field.cqe_prev->field.cqe_next = \
657 (elm)->field.cqe_next; \
658 _Q_INVALIDATE((elm)->field.cqe_prev); \
659 _Q_INVALIDATE((elm)->field.cqe_next); \
660} while (0)
661
662#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
663 if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
664 CIRCLEQ_END(head)) \
665 (head)->cqh_last = (elm2); \
666 else \
667 (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
668 if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
669 CIRCLEQ_END(head)) \
670 (head)->cqh_first = (elm2); \
671 else \
672 (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
673 _Q_INVALIDATE((elm)->field.cqe_prev); \
674 _Q_INVALIDATE((elm)->field.cqe_next); \
675} while (0)
676
677
678/**** amalgamated original file "/deps/pcg_basic.h" ****/
679
680/*
681 * PCG Random Number Generation for C.
682 *
683 * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
684 *
685 * Licensed under the Apache License, Version 2.0 (the "License");
686 * you may not use this file except in compliance with the License.
687 * You may obtain a copy of the License at
688 *
689 * http://www.apache.org/licenses/LICENSE-2.0
690 *
691 * Unless required by applicable law or agreed to in writing, software
692 * distributed under the License is distributed on an "AS IS" BASIS,
693 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
694 * See the License for the specific language governing permissions and
695 * limitations under the License.
696 *
697 * For additional information about the PCG random number generation scheme,
698 * including its license and other licensing options, visit
699 *
700 * http://www.pcg-random.org
701 */
702
703
704
705#ifdef __cplusplus
706extern "C" {
707#endif
708
709typedef struct pcg_state_setseq_64 {
710 uint64_t state; /* RNG state. All values are possible. */
711 uint64_t inc; /* Controls which RNG sequence (stream) is selected. Must
712 * *always* be odd. */
713} pcg32_random_t;
714
715#define PCG32_INITIALIZER { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
716
717void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initial_state, uint64_t initseq);
718uint32_t pcg32_random_r(pcg32_random_t* rng);
719
720#ifdef __cplusplus
721}
722#endif
723
724
725/**** amalgamated original file "/deps/libc_time.h" ****/
726
727
728struct mytm {
729 int tm_sec;
730 int tm_min;
731 int tm_hour;
732 int tm_mday;
733 int tm_mon;
734 int tm_year;
735};
736
737int __secs_to_tm(long long t, struct mytm *tm);
738long long __tm_to_secs(const struct mytm *tm);
739
740
741/**** amalgamated original file "/deps/base64.h" ****/
742
743#ifndef UA_BASE64_H_
744#define UA_BASE64_H_
745
746
747_UA_BEGIN_DECLS
748
749#include <stddef.h>
750
751/**
752 * base64_encode - Base64 encode
753 * @src: Data to be encoded
754 * @len: Length of the data to be encoded
755 * @out_len: Pointer to output length variable
756 * Returns: Allocated buffer of out_len bytes of encoded data,
757 * or %NULL on failure. The output is NOT Null-terminated. */
758unsigned char *
759UA_base64(const unsigned char *src, size_t len, size_t *out_len);
760
761/**
762 * base64_decode - Base64 decode
763 * @src: Data to be decoded
764 * @len: Length of the data to be decoded
765 * @out_len: Pointer to output length variable
766 * Returns: Allocated buffer of out_len bytes of decoded data,
767 * or %NULL on failure. */
768unsigned char *
769UA_unbase64(const unsigned char *src, size_t len, size_t *out_len);
770
771_UA_END_DECLS
772
773#endif /* UA_BASE64_H_ */
774
775/**** amalgamated original file "/src/ua_types_encoding_binary.h" ****/
776
777/* This Source Code Form is subject to the terms of the Mozilla Public
778 * License, v. 2.0. If a copy of the MPL was not distributed with this
779 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
780 *
781 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
782 * Copyright 2015 (c) Sten Grüner
783 * Copyright 2014, 2017 (c) Florian Palm
784 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
785 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
786 */
787
788
789
790_UA_BEGIN_DECLS
791
792typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos,
793 const UA_Byte **bufEnd);
794
795/* Encodes the scalar value described by type in the binary encoding. Encoding
796 * is thread-safe if thread-local variables are enabled. Encoding is also
797 * reentrant and can be safely called from signal handlers or interrupts.
798 *
799 * @param src The value. Must not be NULL.
800 * @param type The value type. Must not be NULL.
801 * @param bufPos Points to a pointer to the current position in the encoding
802 * buffer. Must not be NULL. The pointer is advanced by the number of
803 * encoded bytes, or, if the buffer is exchanged, to the position in the
804 * new buffer.
805 * @param bufEnd Points to a pointer to the end of the encoding buffer (encoding
806 * always stops before *buf_end). Must not be NULL. The pointer is
807 * changed when the buffer is exchanged.
808 * @param exchangeCallback Called when the end of the buffer is reached. This is
809 used to send out a message chunk before continuing with the encoding.
810 Is ignored if NULL.
811 * @param exchangeHandle Custom data passed into the exchangeCallback.
812 * @return Returns a statuscode whether encoding succeeded. */
813UA_StatusCode
814UA_encodeBinaryInternal(const void *src, const UA_DataType *type,
815 UA_Byte **bufPos, const UA_Byte **bufEnd,
816 UA_exchangeEncodeBuffer exchangeCallback,
817 void *exchangeHandle)
818 UA_FUNC_ATTR_WARN_UNUSED_RESULT;
819
820/* Decodes a scalar value described by type from binary encoding. Decoding
821 * is thread-safe if thread-local variables are enabled. Decoding is also
822 * reentrant and can be safely called from signal handlers or interrupts.
823 *
824 * @param src The buffer with the binary encoded value. Must not be NULL.
825 * @param offset The current position in the buffer. Must not be NULL. The value
826 * is advanced as decoding progresses.
827 * @param dst The target value. Must not be NULL. The target is assumed to have
828 * size type->memSize. The value is reset to zero before decoding. If
829 * decoding fails, members are deleted and the value is reset (zeroed)
830 * again.
831 * @param type The value type. Must not be NULL.
832 * @param customTypesSize The number of non-standard datatypes contained in the
833 * customTypes array.
834 * @param customTypes An array of non-standard datatypes (not included in
835 * UA_TYPES). Can be NULL if customTypesSize is zero.
836 * @return Returns a statuscode whether decoding succeeded. */
837UA_StatusCode
838UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
839 void *dst, const UA_DataType *type,
840 const UA_DataTypeArray *customTypes)
841 UA_FUNC_ATTR_WARN_UNUSED_RESULT;
842
843const UA_DataType *
844UA_findDataTypeByBinary(const UA_NodeId *typeId);
845
846_UA_END_DECLS
847
848
849/**** amalgamated original file "/src/ua_util_internal.h" ****/
850
851/* This Source Code Form is subject to the terms of the Mozilla Public
852 * License, v. 2.0. If a copy of the MPL was not distributed with this
853 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
854 *
855 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
856 * Copyright 2014, 2017 (c) Florian Palm
857 * Copyright 2015 (c) LEvertz
858 * Copyright 2015-2016 (c) Sten Grüner
859 * Copyright 2015 (c) Chris Iatrou
860 * Copyright 2015-2016 (c) Oleksiy Vasylyev
861 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
862 * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes)
863 */
864
865
866#define UA_INTERNAL
867
868
869_UA_BEGIN_DECLS
870
871/* Macro-Expand for MSVC workarounds */
872#define UA_MACRO_EXPAND(x) x
873
874/* Print a NodeId in logs */
875#define UA_LOG_NODEID_INTERNAL(NODEID, LOG) \
876 do { \
877 UA_String nodeIdStr = UA_STRING_NULL; \
878 UA_NodeId_print(NODEID, &nodeIdStr); \
879 LOG; \
880 UA_String_clear(&nodeIdStr); \
881 } while(0)
882
883#if UA_LOGLEVEL <= 100
884# define UA_LOG_NODEID_TRACE(NODEID, LOG) \
885 UA_LOG_NODEID_INTERNAL(NODEID, LOG)
886#else
887# define UA_LOG_NODEID_TRACE(NODEID, LOG)
888#endif
889
890#if UA_LOGLEVEL <= 200
891# define UA_LOG_NODEID_DEBUG(NODEID, LOG) \
892 UA_LOG_NODEID_INTERNAL(NODEID, LOG)
893#else
894# define UA_LOG_NODEID_DEBUG(NODEID, LOG)
895#endif
896
897#if UA_LOGLEVEL <= 300
898# define UA_LOG_NODEID_INFO(NODEID, LOG) \
899 UA_LOG_NODEID_INTERNAL(NODEID, LOG)
900#else
901# define UA_LOG_NODEID_INFO(NODEID, LOG)
902#endif
903
904#if UA_LOGLEVEL <= 400
905# define UA_LOG_NODEID_WARNING(NODEID, LOG) \
906 UA_LOG_NODEID_INTERNAL(NODEID, LOG)
907#else
908# define UA_LOG_NODEID_WARNING(NODEID, LOG)
909#endif
910
911#if UA_LOGLEVEL <= 500
912# define UA_LOG_NODEID_ERROR(NODEID, LOG) \
913 UA_LOG_NODEID_INTERNAL(NODEID, LOG)
914#else
915# define UA_LOG_NODEID_ERROR(NODEID, LOG)
916#endif
917
918#if UA_LOGLEVEL <= 600
919# define UA_LOG_NODEID_FATAL(NODEID, LOG) \
920 UA_LOG_NODEID_INTERNAL(NODEID, LOG)
921#else
922# define UA_LOG_NODEID_FATAL(NODEID, LOG)
923#endif
924
925/* Short names for integer. These are not exposed on the public API, since many
926 * user-applications make the same definitions in their headers. */
927typedef UA_Byte u8;
928typedef UA_SByte i8;
929typedef UA_UInt16 u16;
930typedef UA_Int16 i16;
931typedef UA_UInt32 u32;
932typedef UA_Int32 i32;
933typedef UA_UInt64 u64;
934typedef UA_Int64 i64;
935typedef UA_StatusCode status;
936
937/**
938 * Error checking macros
939 */
940
941static UA_INLINE UA_Boolean
942isGood(UA_StatusCode code) {
943 return code == UA_STATUSCODE_GOOD;
944}
945
946static UA_INLINE UA_Boolean
947isNonNull(const void *ptr) {
948 return ptr != NULL;
949}
950
951static UA_INLINE UA_Boolean
952isTrue(uint8_t expr) {
953 return expr;
954}
955
956#define UA_CHECK(A, EVAL_ON_ERROR) \
957 do { \
958 if(UA_UNLIKELY(!isTrue(A))) { \
959 EVAL_ON_ERROR; \
960 } \
961 } while(0)
962
963#define UA_CHECK_STATUS(STATUSCODE, EVAL_ON_ERROR) \
964 UA_CHECK(isGood(STATUSCODE), EVAL_ON_ERROR)
965
966#define UA_CHECK_MEM(STATUSCODE, EVAL_ON_ERROR) \
967 UA_CHECK(isNonNull(STATUSCODE), EVAL_ON_ERROR)
968
969#ifdef UA_DEBUG_FILE_LINE_INFO
970#define UA_CHECK_LOG_INTERNAL(A, STATUSCODE, EVAL, LOG, LOGGER, CAT, MSG, ...) \
971 UA_MACRO_EXPAND( \
972 UA_CHECK(A, LOG(LOGGER, CAT, "" MSG "%s (%s:%d: statuscode: %s)", __VA_ARGS__, \
973 __FILE__, __LINE__, UA_StatusCode_name(STATUSCODE)); \
974 EVAL))
975#else
976#define UA_CHECK_LOG_INTERNAL(A, STATUSCODE, EVAL, LOG, LOGGER, CAT, MSG, ...) \
977 UA_MACRO_EXPAND( \
978 UA_CHECK(A, LOG(LOGGER, CAT, "" MSG "%s (statuscode: %s)", __VA_ARGS__, \
979 UA_StatusCode_name(STATUSCODE)); \
980 EVAL))
981#endif
982
983#define UA_CHECK_LOG(A, EVAL, LEVEL, LOGGER, CAT, ...) \
984 UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(A, UA_STATUSCODE_BAD, EVAL, UA_LOG_##LEVEL, \
985 LOGGER, CAT, __VA_ARGS__, ""))
986
987#define UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, LEVEL, LOGGER, CAT, ...) \
988 UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(isGood(STATUSCODE), STATUSCODE, \
989 EVAL, UA_LOG_##LEVEL, LOGGER, CAT, \
990 __VA_ARGS__, ""))
991
992#define UA_CHECK_MEM_LOG(PTR, EVAL, LEVEL, LOGGER, CAT, ...) \
993 UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(isNonNull(PTR), UA_STATUSCODE_BADOUTOFMEMORY, \
994 EVAL, UA_LOG_##LEVEL, LOGGER, CAT, \
995 __VA_ARGS__, ""))
996
997/**
998 * Check Macros
999 * Usage examples:
1000 *
1001 * void *data = malloc(...);
1002 * UA_CHECK(data, return error);
1003 *
1004 * UA_StatusCode rv = some_func(...);
1005 * UA_CHECK_STATUS(rv, return rv);
1006 *
1007 * UA_Logger *logger = &server->config.logger;
1008 * rv = bar_func(...);
1009 * UA_CHECK_STATUS_WARN(rv, return rv, logger, UA_LOGCATEGORY_SERVER, "msg & args %s", "arg");
1010 */
1011#define UA_CHECK_FATAL(A, EVAL, LOGGER, CAT, ...) \
1012 UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__))
1013#define UA_CHECK_ERROR(A, EVAL, LOGGER, CAT, ...) \
1014 UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__))
1015#define UA_CHECK_WARN(A, EVAL, LOGGER, CAT, ...) \
1016 UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__))
1017#define UA_CHECK_INFO(A, EVAL, LOGGER, CAT, ...) \
1018 UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, INFO, LOGGER, CAT, __VA_ARGS__))
1019
1020#define UA_CHECK_STATUS_FATAL(STATUSCODE, EVAL, LOGGER, CAT, ...) \
1021 UA_MACRO_EXPAND( \
1022 UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__))
1023#define UA_CHECK_STATUS_ERROR(STATUSCODE, EVAL, LOGGER, CAT, ...) \
1024 UA_MACRO_EXPAND( \
1025 UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__))
1026#define UA_CHECK_STATUS_WARN(STATUSCODE, EVAL, LOGGER, CAT, ...) \
1027 UA_MACRO_EXPAND( \
1028 UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__))
1029#define UA_CHECK_STATUS_INFO(STATUSCODE, EVAL, LOGGER, CAT, ...) \
1030 UA_MACRO_EXPAND( \
1031 UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, INFO, LOGGER, CAT, __VA_ARGS__))
1032
1033#define UA_CHECK_MEM_FATAL(PTR, EVAL, LOGGER, CAT, ...) \
1034 UA_MACRO_EXPAND( \
1035 UA_CHECK_MEM_LOG(PTR, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__))
1036#define UA_CHECK_MEM_ERROR(PTR, EVAL, LOGGER, CAT, ...) \
1037 UA_MACRO_EXPAND( \
1038 UA_CHECK_MEM_LOG(PTR, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__))
1039#define UA_CHECK_MEM_WARN(PTR, EVAL, LOGGER, CAT, ...) \
1040 UA_MACRO_EXPAND( \
1041 UA_CHECK_MEM_LOG(PTR, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__))
1042#define UA_CHECK_MEM_INFO(PTR, EVAL, LOGGER, CAT, ...) \
1043 UA_MACRO_EXPAND( \
1044 UA_CHECK_MEM_LOG(PTR, EVAL, INFO, LOGGER, CAT, __VA_ARGS__))
1045
1046/**
1047 * Utility Functions
1048 * ----------------- */
1049
1050const UA_DataType *
1051UA_findDataTypeWithCustom(const UA_NodeId *typeId,
1052 const UA_DataTypeArray *customTypes);
1053
1054/* Get the number of optional fields contained in an structure type */
1055size_t UA_EXPORT
1056getCountOfOptionalFields(const UA_DataType *type);
1057
1058/* Dump packet for debugging / fuzzing */
1059#ifdef UA_DEBUG_DUMP_PKGS
1060void UA_EXPORT
1061UA_dump_hex_pkg(UA_Byte* buffer, size_t bufferLen);
1062#endif
1063
1064/* Unions that represent any of the supported request or response message */
1065typedef union {
1066 UA_RequestHeader requestHeader;
1067 UA_FindServersRequest findServersRequest;
1068 UA_GetEndpointsRequest getEndpointsRequest;
1069#ifdef UA_ENABLE_DISCOVERY
1070# ifdef UA_ENABLE_DISCOVERY_MULTICAST
1071 UA_FindServersOnNetworkRequest findServersOnNetworkRequest;
1072# endif
1073 UA_RegisterServerRequest registerServerRequest;
1074 UA_RegisterServer2Request registerServer2Request;
1075#endif
1076 UA_OpenSecureChannelRequest openSecureChannelRequest;
1077 UA_CreateSessionRequest createSessionRequest;
1078 UA_ActivateSessionRequest activateSessionRequest;
1079 UA_CloseSessionRequest closeSessionRequest;
1080 UA_AddNodesRequest addNodesRequest;
1081 UA_AddReferencesRequest addReferencesRequest;
1082 UA_DeleteNodesRequest deleteNodesRequest;
1083 UA_DeleteReferencesRequest deleteReferencesRequest;
1084 UA_BrowseRequest browseRequest;
1085 UA_BrowseNextRequest browseNextRequest;
1086 UA_TranslateBrowsePathsToNodeIdsRequest translateBrowsePathsToNodeIdsRequest;
1087 UA_RegisterNodesRequest registerNodesRequest;
1088 UA_UnregisterNodesRequest unregisterNodesRequest;
1089 UA_ReadRequest readRequest;
1090 UA_WriteRequest writeRequest;
1091#ifdef UA_ENABLE_HISTORIZING
1092 UA_HistoryReadRequest historyReadRequest;
1093 UA_HistoryUpdateRequest historyUpdateRequest;
1094#endif
1095#ifdef UA_ENABLE_METHODCALLS
1096 UA_CallRequest callRequest;
1097#endif
1098#ifdef UA_ENABLE_SUBSCRIPTIONS
1099 UA_CreateMonitoredItemsRequest createMonitoredItemsRequest;
1100 UA_DeleteMonitoredItemsRequest deleteMonitoredItemsRequest;
1101 UA_ModifyMonitoredItemsRequest modifyMonitoredItemsRequest;
1102 UA_SetMonitoringModeRequest setMonitoringModeRequest;
1103 UA_CreateSubscriptionRequest createSubscriptionRequest;
1104 UA_ModifySubscriptionRequest modifySubscriptionRequest;
1105 UA_SetPublishingModeRequest setPublishingModeRequest;
1106 UA_PublishRequest publishRequest;
1107 UA_RepublishRequest republishRequest;
1108 UA_DeleteSubscriptionsRequest deleteSubscriptionsRequest;
1109#endif
1110} UA_Request;
1111
1112typedef union {
1113 UA_ResponseHeader responseHeader;
1114 UA_FindServersResponse findServersResponse;
1115 UA_GetEndpointsResponse getEndpointsResponse;
1116#ifdef UA_ENABLE_DISCOVERY
1117# ifdef UA_ENABLE_DISCOVERY_MULTICAST
1118 UA_FindServersOnNetworkResponse findServersOnNetworkResponse;
1119# endif
1120 UA_RegisterServerResponse registerServerResponse;
1121 UA_RegisterServer2Response registerServer2Response;
1122#endif
1123 UA_OpenSecureChannelResponse openSecureChannelResponse;
1124 UA_CreateSessionResponse createSessionResponse;
1125 UA_ActivateSessionResponse activateSessionResponse;
1126 UA_CloseSessionResponse closeSessionResponse;
1127 UA_AddNodesResponse addNodesResponse;
1128 UA_AddReferencesResponse addReferencesResponse;
1129 UA_DeleteNodesResponse deleteNodesResponse;
1130 UA_DeleteReferencesResponse deleteReferencesResponse;
1131 UA_BrowseResponse browseResponse;
1132 UA_BrowseNextResponse browseNextResponse;
1133 UA_TranslateBrowsePathsToNodeIdsResponse translateBrowsePathsToNodeIdsResponse;
1134 UA_RegisterNodesResponse registerNodesResponse;
1135 UA_UnregisterNodesResponse unregisterNodesResponse;
1136 UA_ReadResponse readResponse;
1137 UA_WriteResponse writeResponse;
1138#ifdef UA_ENABLE_HISTORIZING
1139 UA_HistoryReadResponse historyReadResponse;
1140 UA_HistoryUpdateResponse historyUpdateResponse;
1141#endif
1142#ifdef UA_ENABLE_METHODCALLS
1143 UA_CallResponse callResponse;
1144#endif
1145#ifdef UA_ENABLE_SUBSCRIPTIONS
1146 UA_CreateMonitoredItemsResponse createMonitoredItemsResponse;
1147 UA_DeleteMonitoredItemsResponse deleteMonitoredItemsResponse;
1148 UA_ModifyMonitoredItemsResponse modifyMonitoredItemsResponse;
1149 UA_SetMonitoringModeResponse setMonitoringModeResponse;
1150 UA_CreateSubscriptionResponse createSubscriptionResponse;
1151 UA_ModifySubscriptionResponse modifySubscriptionResponse;
1152 UA_SetPublishingModeResponse setPublishingModeResponse;
1153 UA_PublishResponse publishResponse;
1154 UA_RepublishResponse republishResponse;
1155 UA_DeleteSubscriptionsResponse deleteSubscriptionsResponse;
1156#endif
1157} UA_Response;
1158
1159/* Do not expose UA_String_equal_ignorecase to public API as it currently only handles
1160 * ASCII strings, and not UTF8! */
1161UA_Boolean UA_EXPORT
1162UA_String_equal_ignorecase(const UA_String *s1, const UA_String *s2);
1163
1164/********************/
1165/* Encoding Helpers */
1166/********************/
1167
1168#define UA_ENCODING_HELPERS(TYPE, UPCASE_TYPE) \
1169 static UA_INLINE size_t \
1170 UA_##TYPE##_calcSizeBinary(const UA_##TYPE *src) { \
1171 return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_##UPCASE_TYPE]); \
1172 } \
1173 static UA_INLINE UA_StatusCode \
1174 UA_##TYPE##_encodeBinary(const UA_##TYPE *src, UA_Byte **bufPos, const UA_Byte *bufEnd) { \
1175 return UA_encodeBinaryInternal(src, &UA_TYPES[UA_TYPES_##UPCASE_TYPE], \
1176 bufPos, &bufEnd, NULL, NULL); \
1177 } \
1178 static UA_INLINE UA_StatusCode \
1179 UA_##TYPE##_decodeBinary(const UA_ByteString *src, size_t *offset, UA_##TYPE *dst) { \
1180 return UA_decodeBinaryInternal(src, offset, dst, \
1181 &UA_TYPES[UA_TYPES_##UPCASE_TYPE], NULL); \
1182 }
1183
1184UA_ENCODING_HELPERS(Boolean, BOOLEAN)
1185UA_ENCODING_HELPERS(SByte, SBYTE)
1186UA_ENCODING_HELPERS(Byte, BYTE)
1187UA_ENCODING_HELPERS(Int16, INT16)
1188UA_ENCODING_HELPERS(UInt16, UINT16)
1189UA_ENCODING_HELPERS(Int32, INT32)
1190UA_ENCODING_HELPERS(UInt32, UINT32)
1191UA_ENCODING_HELPERS(Int64, INT64)
1192UA_ENCODING_HELPERS(UInt64, UINT64)
1193UA_ENCODING_HELPERS(Float, FLOAT)
1194UA_ENCODING_HELPERS(Double, DOUBLE)
1195UA_ENCODING_HELPERS(String, STRING)
1196UA_ENCODING_HELPERS(DateTime, DATETIME)
1197UA_ENCODING_HELPERS(Guid, GUID)
1198UA_ENCODING_HELPERS(ByteString, BYTESTRING)
1199UA_ENCODING_HELPERS(XmlElement, XMLELEMENT)
1200UA_ENCODING_HELPERS(NodeId, NODEID)
1201UA_ENCODING_HELPERS(ExpandedNodeId, EXPANDEDNODEID)
1202UA_ENCODING_HELPERS(StatusCode, STATUSCODE)
1203UA_ENCODING_HELPERS(QualifiedName, QUALIFIEDNAME)
1204UA_ENCODING_HELPERS(LocalizedText, LOCALIZEDTEXT)
1205UA_ENCODING_HELPERS(ExtensionObject, EXTENSIONOBJECT)
1206UA_ENCODING_HELPERS(DataValue, DATAVALUE)
1207UA_ENCODING_HELPERS(Variant, VARIANT)
1208UA_ENCODING_HELPERS(DiagnosticInfo, DIAGNOSTICINFO)
1209
1210_UA_END_DECLS
1211
1212
1213/**** amalgamated original file "/build/src_generated/open62541/transport_generated.h" ****/
1214
1215/**********************************
1216 * Autogenerated -- do not modify *
1217 **********************************/
1218
1219
1220#ifdef UA_ENABLE_AMALGAMATION
1221#else
1222
1223#endif
1224
1225
1226
1227_UA_BEGIN_DECLS
1228
1229
1230/**
1231 * Every type is assigned an index in an array containing the type descriptions.
1232 * These descriptions are used during type handling (copying, deletion,
1233 * binary encoding, ...). */
1234#define UA_TRANSPORT_COUNT 8
1235extern UA_EXPORT const UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT];
1236
1237/**
1238 * MessageType
1239 * ^^^^^^^^^^^
1240 * Message Type and whether the message contains an intermediate chunk */
1241typedef enum {
1242 UA_MESSAGETYPE_ACK = 0x4B4341,
1243 UA_MESSAGETYPE_HEL = 0x4C4548,
1244 UA_MESSAGETYPE_MSG = 0x47534D,
1245 UA_MESSAGETYPE_OPN = 0x4E504F,
1246 UA_MESSAGETYPE_CLO = 0x4F4C43,
1247 UA_MESSAGETYPE_ERR = 0x525245,
1248 UA_MESSAGETYPE_INVALID = 0x0,
1249 __UA_MESSAGETYPE_FORCE32BIT = 0x7fffffff
1250} UA_MessageType;
1251UA_STATIC_ASSERT(sizeof(UA_MessageType) == sizeof(UA_Int32), enum_must_be_32bit);
1252
1253#define UA_TRANSPORT_MESSAGETYPE 0
1254
1255/**
1256 * ChunkType
1257 * ^^^^^^^^^
1258 * Type of the chunk */
1259typedef enum {
1260 UA_CHUNKTYPE_FINAL = 0x46000000,
1261 UA_CHUNKTYPE_INTERMEDIATE = 0x43000000,
1262 UA_CHUNKTYPE_ABORT = 0x41000000,
1263 __UA_CHUNKTYPE_FORCE32BIT = 0x7fffffff
1264} UA_ChunkType;
1265UA_STATIC_ASSERT(sizeof(UA_ChunkType) == sizeof(UA_Int32), enum_must_be_32bit);
1266
1267#define UA_TRANSPORT_CHUNKTYPE 1
1268
1269/**
1270 * TcpMessageHeader
1271 * ^^^^^^^^^^^^^^^^
1272 * TCP Header */
1273typedef struct {
1274 UA_UInt32 messageTypeAndChunkType;
1275 UA_UInt32 messageSize;
1276} UA_TcpMessageHeader;
1277
1278#define UA_TRANSPORT_TCPMESSAGEHEADER 2
1279
1280/**
1281 * TcpHelloMessage
1282 * ^^^^^^^^^^^^^^^
1283 * Hello Message */
1284typedef struct {
1285 UA_UInt32 protocolVersion;
1286 UA_UInt32 receiveBufferSize;
1287 UA_UInt32 sendBufferSize;
1288 UA_UInt32 maxMessageSize;
1289 UA_UInt32 maxChunkCount;
1290 UA_String endpointUrl;
1291} UA_TcpHelloMessage;
1292
1293#define UA_TRANSPORT_TCPHELLOMESSAGE 3
1294
1295/**
1296 * TcpAcknowledgeMessage
1297 * ^^^^^^^^^^^^^^^^^^^^^
1298 * Acknowledge Message */
1299typedef struct {
1300 UA_UInt32 protocolVersion;
1301 UA_UInt32 receiveBufferSize;
1302 UA_UInt32 sendBufferSize;
1303 UA_UInt32 maxMessageSize;
1304 UA_UInt32 maxChunkCount;
1305} UA_TcpAcknowledgeMessage;
1306
1307#define UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE 4
1308
1309/**
1310 * TcpErrorMessage
1311 * ^^^^^^^^^^^^^^^
1312 * Error Message */
1313typedef struct {
1314 UA_UInt32 error;
1315 UA_String reason;
1316} UA_TcpErrorMessage;
1317
1318#define UA_TRANSPORT_TCPERRORMESSAGE 5
1319
1320/**
1321 * AsymmetricAlgorithmSecurityHeader
1322 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1323 * Asymmetric Security Header */
1324typedef struct {
1325 UA_ByteString securityPolicyUri;
1326 UA_ByteString senderCertificate;
1327 UA_ByteString receiverCertificateThumbprint;
1328} UA_AsymmetricAlgorithmSecurityHeader;
1329
1330#define UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER 6
1331
1332/**
1333 * SequenceHeader
1334 * ^^^^^^^^^^^^^^
1335 * Secure Layer Sequence Header */
1336typedef struct {
1337 UA_UInt32 sequenceNumber;
1338 UA_UInt32 requestId;
1339} UA_SequenceHeader;
1340
1341#define UA_TRANSPORT_SEQUENCEHEADER 7
1342
1343
1344_UA_END_DECLS
1345
1346
1347/**** amalgamated original file "/build/src_generated/open62541/transport_generated_handling.h" ****/
1348
1349/**********************************
1350 * Autogenerated -- do not modify *
1351 **********************************/
1352
1353
1354
1355_UA_BEGIN_DECLS
1356
1357#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6
1358# pragma GCC diagnostic push
1359# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
1360# pragma GCC diagnostic ignored "-Wmissing-braces"
1361#endif
1362
1363
1364/* MessageType */
1365static UA_INLINE void
1366UA_MessageType_init(UA_MessageType *p) {
1367 memset(s: p, c: 0, n: sizeof(UA_MessageType));
1368}
1369
1370static UA_INLINE UA_MessageType *
1371UA_MessageType_new(void) {
1372 return (UA_MessageType*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
1373}
1374
1375static UA_INLINE UA_StatusCode
1376UA_MessageType_copy(const UA_MessageType *src, UA_MessageType *dst) {
1377 return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
1378}
1379
1380UA_DEPRECATED static UA_INLINE void
1381UA_MessageType_deleteMembers(UA_MessageType *p) {
1382 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
1383}
1384
1385static UA_INLINE void
1386UA_MessageType_clear(UA_MessageType *p) {
1387 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
1388}
1389
1390static UA_INLINE void
1391UA_MessageType_delete(UA_MessageType *p) {
1392 UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]);
1393}
1394
1395/* ChunkType */
1396static UA_INLINE void
1397UA_ChunkType_init(UA_ChunkType *p) {
1398 memset(s: p, c: 0, n: sizeof(UA_ChunkType));
1399}
1400
1401static UA_INLINE UA_ChunkType *
1402UA_ChunkType_new(void) {
1403 return (UA_ChunkType*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
1404}
1405
1406static UA_INLINE UA_StatusCode
1407UA_ChunkType_copy(const UA_ChunkType *src, UA_ChunkType *dst) {
1408 return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
1409}
1410
1411UA_DEPRECATED static UA_INLINE void
1412UA_ChunkType_deleteMembers(UA_ChunkType *p) {
1413 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
1414}
1415
1416static UA_INLINE void
1417UA_ChunkType_clear(UA_ChunkType *p) {
1418 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
1419}
1420
1421static UA_INLINE void
1422UA_ChunkType_delete(UA_ChunkType *p) {
1423 UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]);
1424}
1425
1426/* TcpMessageHeader */
1427static UA_INLINE void
1428UA_TcpMessageHeader_init(UA_TcpMessageHeader *p) {
1429 memset(s: p, c: 0, n: sizeof(UA_TcpMessageHeader));
1430}
1431
1432static UA_INLINE UA_TcpMessageHeader *
1433UA_TcpMessageHeader_new(void) {
1434 return (UA_TcpMessageHeader*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
1435}
1436
1437static UA_INLINE UA_StatusCode
1438UA_TcpMessageHeader_copy(const UA_TcpMessageHeader *src, UA_TcpMessageHeader *dst) {
1439 return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
1440}
1441
1442UA_DEPRECATED static UA_INLINE void
1443UA_TcpMessageHeader_deleteMembers(UA_TcpMessageHeader *p) {
1444 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
1445}
1446
1447static UA_INLINE void
1448UA_TcpMessageHeader_clear(UA_TcpMessageHeader *p) {
1449 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
1450}
1451
1452static UA_INLINE void
1453UA_TcpMessageHeader_delete(UA_TcpMessageHeader *p) {
1454 UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]);
1455}
1456
1457/* TcpHelloMessage */
1458static UA_INLINE void
1459UA_TcpHelloMessage_init(UA_TcpHelloMessage *p) {
1460 memset(s: p, c: 0, n: sizeof(UA_TcpHelloMessage));
1461}
1462
1463static UA_INLINE UA_TcpHelloMessage *
1464UA_TcpHelloMessage_new(void) {
1465 return (UA_TcpHelloMessage*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
1466}
1467
1468static UA_INLINE UA_StatusCode
1469UA_TcpHelloMessage_copy(const UA_TcpHelloMessage *src, UA_TcpHelloMessage *dst) {
1470 return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
1471}
1472
1473UA_DEPRECATED static UA_INLINE void
1474UA_TcpHelloMessage_deleteMembers(UA_TcpHelloMessage *p) {
1475 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
1476}
1477
1478static UA_INLINE void
1479UA_TcpHelloMessage_clear(UA_TcpHelloMessage *p) {
1480 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
1481}
1482
1483static UA_INLINE void
1484UA_TcpHelloMessage_delete(UA_TcpHelloMessage *p) {
1485 UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]);
1486}
1487
1488/* TcpAcknowledgeMessage */
1489static UA_INLINE void
1490UA_TcpAcknowledgeMessage_init(UA_TcpAcknowledgeMessage *p) {
1491 memset(s: p, c: 0, n: sizeof(UA_TcpAcknowledgeMessage));
1492}
1493
1494static UA_INLINE UA_TcpAcknowledgeMessage *
1495UA_TcpAcknowledgeMessage_new(void) {
1496 return (UA_TcpAcknowledgeMessage*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
1497}
1498
1499static UA_INLINE UA_StatusCode
1500UA_TcpAcknowledgeMessage_copy(const UA_TcpAcknowledgeMessage *src, UA_TcpAcknowledgeMessage *dst) {
1501 return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
1502}
1503
1504UA_DEPRECATED static UA_INLINE void
1505UA_TcpAcknowledgeMessage_deleteMembers(UA_TcpAcknowledgeMessage *p) {
1506 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
1507}
1508
1509static UA_INLINE void
1510UA_TcpAcknowledgeMessage_clear(UA_TcpAcknowledgeMessage *p) {
1511 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
1512}
1513
1514static UA_INLINE void
1515UA_TcpAcknowledgeMessage_delete(UA_TcpAcknowledgeMessage *p) {
1516 UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]);
1517}
1518
1519/* TcpErrorMessage */
1520static UA_INLINE void
1521UA_TcpErrorMessage_init(UA_TcpErrorMessage *p) {
1522 memset(s: p, c: 0, n: sizeof(UA_TcpErrorMessage));
1523}
1524
1525static UA_INLINE UA_TcpErrorMessage *
1526UA_TcpErrorMessage_new(void) {
1527 return (UA_TcpErrorMessage*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
1528}
1529
1530static UA_INLINE UA_StatusCode
1531UA_TcpErrorMessage_copy(const UA_TcpErrorMessage *src, UA_TcpErrorMessage *dst) {
1532 return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
1533}
1534
1535UA_DEPRECATED static UA_INLINE void
1536UA_TcpErrorMessage_deleteMembers(UA_TcpErrorMessage *p) {
1537 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
1538}
1539
1540static UA_INLINE void
1541UA_TcpErrorMessage_clear(UA_TcpErrorMessage *p) {
1542 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
1543}
1544
1545static UA_INLINE void
1546UA_TcpErrorMessage_delete(UA_TcpErrorMessage *p) {
1547 UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]);
1548}
1549
1550/* AsymmetricAlgorithmSecurityHeader */
1551static UA_INLINE void
1552UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader *p) {
1553 memset(s: p, c: 0, n: sizeof(UA_AsymmetricAlgorithmSecurityHeader));
1554}
1555
1556static UA_INLINE UA_AsymmetricAlgorithmSecurityHeader *
1557UA_AsymmetricAlgorithmSecurityHeader_new(void) {
1558 return (UA_AsymmetricAlgorithmSecurityHeader*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
1559}
1560
1561static UA_INLINE UA_StatusCode
1562UA_AsymmetricAlgorithmSecurityHeader_copy(const UA_AsymmetricAlgorithmSecurityHeader *src, UA_AsymmetricAlgorithmSecurityHeader *dst) {
1563 return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
1564}
1565
1566UA_DEPRECATED static UA_INLINE void
1567UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader *p) {
1568 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
1569}
1570
1571static UA_INLINE void
1572UA_AsymmetricAlgorithmSecurityHeader_clear(UA_AsymmetricAlgorithmSecurityHeader *p) {
1573 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
1574}
1575
1576static UA_INLINE void
1577UA_AsymmetricAlgorithmSecurityHeader_delete(UA_AsymmetricAlgorithmSecurityHeader *p) {
1578 UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]);
1579}
1580
1581/* SequenceHeader */
1582static UA_INLINE void
1583UA_SequenceHeader_init(UA_SequenceHeader *p) {
1584 memset(s: p, c: 0, n: sizeof(UA_SequenceHeader));
1585}
1586
1587static UA_INLINE UA_SequenceHeader *
1588UA_SequenceHeader_new(void) {
1589 return (UA_SequenceHeader*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
1590}
1591
1592static UA_INLINE UA_StatusCode
1593UA_SequenceHeader_copy(const UA_SequenceHeader *src, UA_SequenceHeader *dst) {
1594 return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
1595}
1596
1597UA_DEPRECATED static UA_INLINE void
1598UA_SequenceHeader_deleteMembers(UA_SequenceHeader *p) {
1599 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
1600}
1601
1602static UA_INLINE void
1603UA_SequenceHeader_clear(UA_SequenceHeader *p) {
1604 UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
1605}
1606
1607static UA_INLINE void
1608UA_SequenceHeader_delete(UA_SequenceHeader *p) {
1609 UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]);
1610}
1611
1612#if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6
1613# pragma GCC diagnostic pop
1614#endif
1615
1616_UA_END_DECLS
1617
1618
1619/**** amalgamated original file "/src/ua_connection_internal.h" ****/
1620
1621/* This Source Code Form is subject to the terms of the Mozilla Public
1622 * License, v. 2.0. If a copy of the MPL was not distributed with this
1623 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
1624 *
1625 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
1626 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
1627 * Copyright 2017 (c) Florian Palm
1628 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
1629 */
1630
1631
1632
1633_UA_BEGIN_DECLS
1634
1635/* When a fatal error occurs the Server shall send an Error Message to the
1636 * Client and close the socket. When a Client encounters one of these errors, it
1637 * shall also close the socket but does not send an Error Message. After the
1638 * socket is closed a Client shall try to reconnect automatically using the
1639 * mechanisms described in [...]. */
1640void
1641UA_Connection_sendError(UA_Connection *connection,
1642 UA_TcpErrorMessage *error);
1643
1644void UA_Connection_detachSecureChannel(UA_Connection *connection);
1645void UA_Connection_attachSecureChannel(UA_Connection *connection,
1646 UA_SecureChannel *channel);
1647
1648_UA_END_DECLS
1649
1650
1651/**** amalgamated original file "/src/ua_securechannel.h" ****/
1652
1653/* This Source Code Form is subject to the terms of the Mozilla Public
1654 * License, v. 2.0. If a copy of the MPL was not distributed with this
1655 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
1656 *
1657 * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
1658 * Copyright 2017 (c) Florian Palm
1659 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
1660 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
1661 */
1662
1663
1664
1665
1666_UA_BEGIN_DECLS
1667
1668/* The message header of the OPC UA binary protocol is structured as follows:
1669 *
1670 * - MessageType (3 Byte)
1671 * - IsFinal (1 Byte)
1672 * - MessageSize (4 Byte)
1673 * *** UA_SECURECHANNEL_MESSAGEHEADER_LENGTH ***
1674 * - SecureChannelId (4 Byte)
1675 * *** UA_SECURECHANNEL_CHANNELHEADER_LENGTH ***
1676 * - SecurityHeader (4 Byte TokenId for symmetric, otherwise dynamic length)
1677 * - SequenceHeader (8 Byte)
1678 * - SequenceNumber
1679 * - RequestId
1680 */
1681
1682#define UA_SECURECHANNEL_MESSAGEHEADER_LENGTH 8
1683#define UA_SECURECHANNEL_CHANNELHEADER_LENGTH 12
1684#define UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH 4
1685#define UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH 8
1686#define UA_SECURECHANNEL_SYMMETRIC_HEADER_UNENCRYPTEDLENGTH \
1687 (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + \
1688 UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH)
1689#define UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH \
1690 (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + \
1691 UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH + \
1692 UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH)
1693
1694/* Minimum length of a valid message (ERR message with an empty reason) */
1695#define UA_SECURECHANNEL_MESSAGE_MIN_LENGTH 16
1696
1697/* Thread-local variables to force failure modes during testing */
1698#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
1699extern UA_StatusCode decrypt_verifySignatureFailure;
1700extern UA_StatusCode sendAsym_sendFailure;
1701extern UA_StatusCode processSym_seqNumberFailure;
1702#endif
1703
1704/* The Session implementation differs between client and server. Still, it is
1705 * expected that the Session structure begins with the SessionHeader. This is
1706 * the interface that will be used by the SecureChannel. The lifecycle of
1707 * Sessions is independent of the underlying SecureChannel. But every Session
1708 * can be attached to only one SecureChannel. */
1709typedef struct UA_SessionHeader {
1710 SLIST_ENTRY(UA_SessionHeader) next;
1711 UA_NodeId authenticationToken;
1712 UA_Boolean serverSession; /* Disambiguate client and server session */
1713 UA_SecureChannel *channel; /* The pointer back to the SecureChannel in the session. */
1714} UA_SessionHeader;
1715
1716/* For chunked requests */
1717typedef struct UA_Chunk {
1718 SIMPLEQ_ENTRY(UA_Chunk) pointers;
1719 UA_ByteString bytes;
1720 UA_MessageType messageType;
1721 UA_ChunkType chunkType;
1722 UA_UInt32 requestId;
1723 UA_Boolean copied; /* Do the bytes point to a buffer from the network or was
1724 * memory allocated for the chunk separately */
1725} UA_Chunk;
1726
1727typedef SIMPLEQ_HEAD(UA_ChunkQueue, UA_Chunk) UA_ChunkQueue;
1728
1729typedef enum {
1730 UA_SECURECHANNELRENEWSTATE_NORMAL,
1731
1732 /* Client has sent an OPN, but not received a response so far. */
1733 UA_SECURECHANNELRENEWSTATE_SENT,
1734
1735 /* The server waits for the first request with the new token for the rollover.
1736 * The new token is stored in the altSecurityToken. The configured local and
1737 * remote symmetric encryption keys are the old ones. */
1738 UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER,
1739
1740 /* The client already uses the new token. But he waits for the server to respond
1741 * with the new token to complete the rollover. The old token is stored in
1742 * altSecurityToken. The local symmetric encryption key is new. The remote
1743 * encryption key is the old one. */
1744 UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT
1745} UA_SecureChannelRenewState;
1746
1747struct UA_SecureChannel {
1748 UA_SecureChannelState state;
1749 UA_SecureChannelRenewState renewState;
1750 UA_MessageSecurityMode securityMode;
1751 UA_ConnectionConfig config;
1752
1753 /* Rules for revolving the token with a renew OPN request: The client is
1754 * allowed to accept messages with the old token until the OPN response has
1755 * arrived. The server accepts the old token until one message secured with
1756 * the new token has arrived.
1757 *
1758 * We recognize whether nextSecurityToken contains a valid next token if the
1759 * ChannelId is not 0. */
1760 UA_ChannelSecurityToken securityToken; /* Also contains the channelId */
1761 UA_ChannelSecurityToken altSecurityToken; /* Alternative token for the rollover.
1762 * See the renewState. */
1763
1764 /* The endpoint and context of the channel */
1765 const UA_SecurityPolicy *securityPolicy;
1766 void *channelContext; /* For interaction with the security policy */
1767 UA_Connection *connection;
1768
1769 /* Asymmetric encryption info */
1770 UA_ByteString remoteCertificate;
1771 UA_Byte remoteCertificateThumbprint[20]; /* The thumbprint of the remote certificate */
1772
1773 /* Symmetric encryption nonces. These are used to generate the key material
1774 * and must not be reused once the keys are in place.
1775 *
1776 * Nonces are also used during the CreateSession / ActivateSession
1777 * handshake. These are not handled here, as the Session handling can
1778 * overlap with a RenewSecureChannel. */
1779 UA_ByteString remoteNonce;
1780 UA_ByteString localNonce;
1781
1782 UA_UInt32 receiveSequenceNumber;
1783 UA_UInt32 sendSequenceNumber;
1784
1785 /* Sessions that are bound to the SecureChannel */
1786 SLIST_HEAD(, UA_SessionHeader) sessions;
1787
1788 /* If a buffer is received, first all chunks are put into the completeChunks
1789 * queue. Then they are processed in order. This ensures that processing
1790 * buffers is reentrant with the correct processing order. (This has lead to
1791 * problems in the client in the past.) */
1792 UA_ChunkQueue completeChunks; /* Received full chunks that have not been
1793 * decrypted so far */
1794 UA_ChunkQueue decryptedChunks; /* Received chunks that were decrypted but
1795 * not processed */
1796 size_t decryptedChunksCount;
1797 size_t decryptedChunksLength;
1798 UA_ByteString incompleteChunk; /* A half-received chunk (TCP is a
1799 * streaming protocol) is stored here */
1800
1801 UA_CertificateVerification *certificateVerification;
1802 UA_StatusCode (*processOPNHeader)(void *application, UA_SecureChannel *channel,
1803 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader);
1804};
1805
1806void UA_SecureChannel_init(UA_SecureChannel *channel,
1807 const UA_ConnectionConfig *config);
1808
1809void UA_SecureChannel_close(UA_SecureChannel *channel);
1810
1811/* Process the remote configuration in the HEL/ACK handshake. The connection
1812 * config is initialized with the local settings. */
1813UA_StatusCode
1814UA_SecureChannel_processHELACK(UA_SecureChannel *channel,
1815 const UA_TcpAcknowledgeMessage *remoteConfig);
1816
1817UA_StatusCode
1818UA_SecureChannel_setSecurityPolicy(UA_SecureChannel *channel,
1819 const UA_SecurityPolicy *securityPolicy,
1820 const UA_ByteString *remoteCertificate);
1821
1822/* Remove (partially) received unprocessed chunks */
1823void
1824UA_SecureChannel_deleteBuffered(UA_SecureChannel *channel);
1825
1826/* Wrapper function for generating a local nonce for the supplied channel. Uses
1827 * the random generator of the channels security policy to allocate and generate
1828 * a nonce with the specified length. */
1829UA_StatusCode
1830UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel);
1831
1832UA_StatusCode
1833UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel);
1834
1835UA_StatusCode
1836generateRemoteKeys(const UA_SecureChannel *channel);
1837
1838/**
1839 * Sending Messages
1840 * ---------------- */
1841
1842UA_StatusCode
1843UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
1844 const void *content, const UA_DataType *contentType);
1845
1846UA_StatusCode
1847UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
1848 UA_MessageType messageType, void *payload,
1849 const UA_DataType *payloadType);
1850
1851/* The MessageContext is forwarded into the encoding layer so that we can send
1852 * chunks before continuing to encode. This lets us reuse a fixed chunk-sized
1853 * messages buffer. */
1854typedef struct {
1855 UA_SecureChannel *channel;
1856 UA_UInt32 requestId;
1857 UA_UInt32 messageType;
1858
1859 UA_UInt16 chunksSoFar;
1860 size_t messageSizeSoFar;
1861
1862 UA_ByteString messageBuffer;
1863 UA_Byte *buf_pos;
1864 const UA_Byte *buf_end;
1865
1866 UA_Boolean final;
1867} UA_MessageContext;
1868
1869/* Start the context of a new symmetric message. */
1870UA_StatusCode
1871UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
1872 UA_UInt32 requestId, UA_MessageType messageType);
1873
1874/* Encode the content and send out full chunks. If the return code is good, then
1875 * the ChunkInfo contains encoded content that has not been sent. If the return
1876 * code is bad, then the ChunkInfo has been cleaned up internally. */
1877UA_StatusCode
1878UA_MessageContext_encode(UA_MessageContext *mc, const void *content,
1879 const UA_DataType *contentType);
1880
1881/* Sends a symmetric message already encoded in the context. The context is
1882 * cleaned up, also in case of errors. */
1883UA_StatusCode
1884UA_MessageContext_finish(UA_MessageContext *mc);
1885
1886/* To be used when a failure occures when a MessageContext is open. Note that
1887 * the _encode and _finish methods will clean up internally. _abort can be run
1888 * on a MessageContext that has already been cleaned up before. */
1889void
1890UA_MessageContext_abort(UA_MessageContext *mc);
1891
1892/**
1893 * Receive Message
1894 * --------------- */
1895
1896typedef UA_StatusCode
1897(UA_ProcessMessageCallback)(void *application, UA_SecureChannel *channel,
1898 UA_MessageType messageType, UA_UInt32 requestId,
1899 UA_ByteString *message);
1900
1901/* Process a received buffer. The callback function is called with the message
1902 * body if the message is complete. The message is removed afterwards. Returns
1903 * if an irrecoverable error occured.
1904 *
1905 * Note that only MSG and CLO messages are decrypted. HEL/ACK/OPN/... are
1906 * forwarded verbatim to the application. */
1907UA_StatusCode
1908UA_SecureChannel_processBuffer(UA_SecureChannel *channel, void *application,
1909 UA_ProcessMessageCallback callback,
1910 const UA_ByteString *buffer);
1911
1912/* Try to receive at least one complete chunk on the connection. This blocks the
1913 * current thread up to the given timeout. It will return once the first buffer
1914 * has been received (and possibly processed when the message is complete).
1915 *
1916 * @param channel The SecureChannel
1917 * @param application The client or server application
1918 * @param callback The function pointer for processing complete messages
1919 * @param timeout The timeout (in milliseconds) the method will block at most.
1920 * @return Returns UA_STATUSCODE_GOOD or an error code. A timeout does not
1921 * create an error. */
1922UA_StatusCode
1923UA_SecureChannel_receive(UA_SecureChannel *channel, void *application,
1924 UA_ProcessMessageCallback callback, UA_UInt32 timeout);
1925
1926/* Internal methods in ua_securechannel_crypto.h */
1927
1928void
1929hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
1930 const UA_Byte **buf_end);
1931
1932/* Decrypt and verify via the signature. The chunk buffer is reused to hold the
1933 * decrypted data after the MessageHeader and SecurityHeader. The chunk length
1934 * is reduced by the signature, padding and encryption overhead.
1935 *
1936 * The offset argument points to the start of the encrypted content (beginning
1937 * with the SequenceHeader).*/
1938UA_StatusCode
1939decryptAndVerifyChunk(const UA_SecureChannel *channel,
1940 const UA_SecurityPolicyCryptoModule *cryptoModule,
1941 UA_MessageType messageType, UA_ByteString *chunk,
1942 size_t offset);
1943
1944size_t
1945calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel);
1946
1947UA_StatusCode
1948prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
1949 const UA_Byte *buf_end, size_t totalLength,
1950 size_t securityHeaderLength, UA_UInt32 requestId,
1951 size_t *const finalLength);
1952
1953void
1954setBufPos(UA_MessageContext *mc);
1955
1956UA_StatusCode
1957checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId);
1958
1959UA_StatusCode
1960checkAsymHeader(UA_SecureChannel *channel,
1961 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader);
1962
1963void
1964padChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cm,
1965 const UA_Byte *start, UA_Byte **pos);
1966
1967UA_StatusCode
1968signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength,
1969 UA_ByteString *buf, size_t securityHeaderLength,
1970 size_t totalLength);
1971
1972UA_StatusCode
1973signAndEncryptSym(UA_MessageContext *messageContext,
1974 size_t preSigLength, size_t totalLength);
1975
1976/**
1977 * Log Helper
1978 * ----------
1979 * C99 requires at least one element for the variadic argument. If the log
1980 * statement has no variable arguments, supply an additional NULL. It will be
1981 * ignored by printf.
1982 *
1983 * We have to jump through some hoops to enable the use of format strings
1984 * without arguments since (pedantic) C99 does not allow variadic macros with
1985 * zero arguments. So we add a dummy argument that is not printed (%.0s is
1986 * string of length zero). */
1987
1988#define UA_LOG_TRACE_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
1989 UA_LOG_TRACE(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
1990 "Connection %i | SecureChannel %" PRIu32 " | " MSG "%.0s", \
1991 ((CHANNEL)->connection ? (int)((CHANNEL)->connection->sockfd) : 0), \
1992 (CHANNEL)->securityToken.channelId, __VA_ARGS__)
1993
1994#define UA_LOG_TRACE_CHANNEL(LOGGER, CHANNEL, ...) \
1995 UA_MACRO_EXPAND(UA_LOG_TRACE_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
1996
1997#define UA_LOG_DEBUG_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
1998 UA_LOG_DEBUG(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
1999 "Connection %i | SecureChannel %" PRIu32 " | " MSG "%.0s", \
2000 ((CHANNEL)->connection ? (int)((CHANNEL)->connection->sockfd) : 0), \
2001 (CHANNEL)->securityToken.channelId, __VA_ARGS__)
2002
2003#define UA_LOG_DEBUG_CHANNEL(LOGGER, CHANNEL, ...) \
2004 UA_MACRO_EXPAND(UA_LOG_DEBUG_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
2005
2006#define UA_LOG_INFO_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
2007 UA_LOG_INFO(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
2008 "Connection %i | SecureChannel %" PRIu32 " | " MSG "%.0s", \
2009 ((CHANNEL)->connection ? (int)((CHANNEL)->connection->sockfd) : 0), \
2010 (CHANNEL)->securityToken.channelId, __VA_ARGS__)
2011
2012#define UA_LOG_INFO_CHANNEL(LOGGER, CHANNEL, ...) \
2013 UA_MACRO_EXPAND(UA_LOG_INFO_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
2014
2015#define UA_LOG_WARNING_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
2016 UA_LOG_WARNING(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
2017 "Connection %i | SecureChannel %" PRIu32 " | " MSG "%.0s", \
2018 ((CHANNEL)->connection ? (int)((CHANNEL)->connection->sockfd) : 0), \
2019 (CHANNEL)->securityToken.channelId, __VA_ARGS__)
2020
2021#define UA_LOG_WARNING_CHANNEL(LOGGER, CHANNEL, ...) \
2022 UA_MACRO_EXPAND(UA_LOG_WARNING_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
2023
2024#define UA_LOG_ERROR_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
2025 UA_LOG_ERROR(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
2026 "Connection %i | SecureChannel %" PRIu32 " | " MSG "%.0s", \
2027 ((CHANNEL)->connection ? (int)((CHANNEL)->connection->sockfd) : 0), \
2028 (CHANNEL)->securityToken.channelId, __VA_ARGS__)
2029
2030#define UA_LOG_ERROR_CHANNEL(LOGGER, CHANNEL, ...) \
2031 UA_MACRO_EXPAND(UA_LOG_ERROR_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
2032
2033#define UA_LOG_FATAL_CHANNEL_INTERNAL(LOGGER, CHANNEL, MSG, ...) \
2034 UA_LOG_FATAL(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \
2035 "Connection %i | SecureChannel %" PRIu32 " | " MSG "%.0s", \
2036 ((CHANNEL)->connection ? (CHANNEL)->connection->sockfd : 0), \
2037 (CHANNEL)->securityToken.channelId, __VA_ARGS__)
2038
2039#define UA_LOG_FATAL_CHANNEL(LOGGER, CHANNEL, ...) \
2040 UA_MACRO_EXPAND(UA_LOG_FATAL_CHANNEL_INTERNAL(LOGGER, CHANNEL, __VA_ARGS__, ""))
2041
2042_UA_END_DECLS
2043
2044
2045/**** amalgamated original file "/src/ua_timer.h" ****/
2046
2047/* This Source Code Form is subject to the terms of the Mozilla Public
2048 * License, v. 2.0. If a copy of the MPL was not distributed with this
2049 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
2050 *
2051 * Copyright 2017, 2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
2052 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
2053 */
2054
2055
2056
2057_UA_BEGIN_DECLS
2058
2059/* The timer is protected by its own mutex. The mutex is released before calling
2060 * into the callbacks. So the timer can be modified from the callbacks it is
2061 * executing. Also, the timer mutex can never lead to locking. Because the timer
2062 * mutex will be left without acquiring another mutex.
2063 *
2064 * Obviously, the timer must not be deleted from within one of its
2065 * callbacks. */
2066
2067/* Callback where the application is either a client or a server */
2068typedef void (*UA_ApplicationCallback)(void *application, void *data);
2069
2070typedef struct UA_TimerEntry {
2071 struct aa_entry treeEntry;
2072 UA_TimerPolicy timerPolicy; /* Timer policy to handle cycle misses */
2073 UA_DateTime nextTime; /* The next time when the callback
2074 * is to be executed */
2075 UA_UInt64 interval; /* Interval in 100ns resolution. If
2076 the interval is zero, the
2077 callback is not repeated and
2078 removed after execution. */
2079 UA_ApplicationCallback callback;
2080 void *application;
2081 void *data;
2082
2083 struct aa_entry idTreeEntry;
2084 UA_UInt64 id; /* Id of the entry */
2085} UA_TimerEntry;
2086
2087typedef struct {
2088 struct aa_head root; /* The root of the time-sorted tree */
2089 struct aa_head idRoot; /* The root of the id-sorted tree */
2090 UA_UInt64 idCounter; /* Generate unique identifiers. Identifiers are
2091 * always above zero. */
2092#if UA_MULTITHREADING >= 100
2093 UA_Lock timerMutex;
2094#endif
2095} UA_Timer;
2096
2097void
2098UA_Timer_init(UA_Timer *t);
2099
2100UA_StatusCode
2101UA_Timer_addTimedCallback(UA_Timer *t, UA_ApplicationCallback callback,
2102 void *application, void *data, UA_DateTime date,
2103 UA_UInt64 *callbackId);
2104
2105/* Add a pre-allocated and pre-filled UA_TimerEntry. This cannot fail. It is
2106 * used, for example, for delayed memory reclamation where the data structure
2107 * begins with a UA_TimerEntry. */
2108void
2109UA_Timer_addTimerEntry(UA_Timer *t, UA_TimerEntry *te, UA_UInt64 *callbackId);
2110
2111UA_StatusCode
2112UA_Timer_addRepeatedCallback(UA_Timer *t, UA_ApplicationCallback callback,
2113 void *application, void *data, UA_Double interval_ms,
2114 UA_DateTime *baseTime, UA_TimerPolicy timerPolicy,
2115 UA_UInt64 *callbackId);
2116
2117UA_StatusCode
2118UA_Timer_changeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId,
2119 UA_Double interval_ms, UA_DateTime *baseTime,
2120 UA_TimerPolicy timerPolicy);
2121
2122void
2123UA_Timer_removeCallback(UA_Timer *t, UA_UInt64 callbackId);
2124
2125/* Process (dispatch) the repeated callbacks that have timed out. Returns the
2126 * timestamp of the next scheduled repeated callback. Not thread-safe.
2127 * Application is a pointer to the client / server environment for the callback.
2128 * Dispatched is set to true when at least one callback was run / dispatched. */
2129typedef void
2130(*UA_TimerExecutionCallback)(void *executionApplication, UA_ApplicationCallback cb,
2131 void *callbackApplication, void *data);
2132
2133UA_DateTime
2134UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic,
2135 UA_TimerExecutionCallback executionCallback,
2136 void *executionApplication);
2137
2138void
2139UA_Timer_clear(UA_Timer *t);
2140
2141_UA_END_DECLS
2142
2143
2144/**** amalgamated original file "/src/server/ua_session.h" ****/
2145
2146/* This Source Code Form is subject to the terms of the Mozilla Public
2147 * License, v. 2.0. If a copy of the MPL was not distributed with this
2148 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
2149 *
2150 * Copyright 2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
2151 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
2152 */
2153
2154
2155
2156
2157_UA_BEGIN_DECLS
2158
2159#define UA_MAXCONTINUATIONPOINTS 5
2160
2161struct ContinuationPoint;
2162typedef struct ContinuationPoint ContinuationPoint;
2163
2164/* Returns the next entry in the linked list */
2165ContinuationPoint *
2166ContinuationPoint_clear(ContinuationPoint *cp);
2167
2168struct UA_Subscription;
2169typedef struct UA_Subscription UA_Subscription;
2170
2171#ifdef UA_ENABLE_SUBSCRIPTIONS
2172typedef struct UA_PublishResponseEntry {
2173 SIMPLEQ_ENTRY(UA_PublishResponseEntry) listEntry;
2174 UA_UInt32 requestId;
2175 UA_PublishResponse response;
2176} UA_PublishResponseEntry;
2177#endif
2178
2179typedef struct {
2180 UA_SessionHeader header;
2181 UA_ApplicationDescription clientDescription;
2182 UA_String sessionName;
2183 UA_Boolean activated;
2184 void *sessionHandle; /* pointer assigned in userland-callback */
2185 UA_NodeId sessionId;
2186 UA_UInt32 maxRequestMessageSize;
2187 UA_UInt32 maxResponseMessageSize;
2188 UA_Double timeout; /* in ms */
2189 UA_DateTime validTill;
2190 UA_ByteString serverNonce;
2191
2192 UA_UInt16 availableContinuationPoints;
2193 ContinuationPoint *continuationPoints;
2194
2195 size_t paramsSize;
2196 UA_KeyValuePair *params;
2197
2198 /* Localization information */
2199 size_t localeIdsSize;
2200 UA_String *localeIds;
2201
2202#ifdef UA_ENABLE_SUBSCRIPTIONS
2203 /* The queue is ordered according to the priority byte (higher bytes come
2204 * first). When a late subscription finally publishes, then it is pushed to
2205 * the back within the sub-set of subscriptions that has the same priority
2206 * (round-robin scheduling). */
2207 size_t subscriptionsSize;
2208 TAILQ_HEAD(, UA_Subscription) subscriptions;
2209
2210 size_t responseQueueSize;
2211 SIMPLEQ_HEAD(, UA_PublishResponseEntry) responseQueue;
2212
2213 size_t totalRetransmissionQueueSize; /* Retransmissions of all subscriptions */
2214#endif
2215
2216#ifdef UA_ENABLE_DIAGNOSTICS
2217 UA_SessionSecurityDiagnosticsDataType securityDiagnostics;
2218 UA_SessionDiagnosticsDataType diagnostics;
2219#endif
2220} UA_Session;
2221
2222/**
2223 * Session Lifecycle
2224 * ----------------- */
2225
2226void UA_Session_init(UA_Session *session);
2227void UA_Session_clear(UA_Session *session, UA_Server *server);
2228void UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel);
2229void UA_Session_detachFromSecureChannel(UA_Session *session);
2230UA_StatusCode UA_Session_generateNonce(UA_Session *session);
2231
2232/* If any activity on a session happens, the timeout is extended */
2233void UA_Session_updateLifetime(UA_Session *session);
2234
2235/**
2236 * Subscription handling
2237 * --------------------- */
2238
2239#ifdef UA_ENABLE_SUBSCRIPTIONS
2240
2241void
2242UA_Session_attachSubscription(UA_Session *session, UA_Subscription *sub);
2243
2244/* If releasePublishResponses is true and the last subscription is removed, all
2245 * outstanding PublishResponse are sent with a StatusCode. But we don't do that
2246 * if a Subscription is only detached for modification. */
2247void
2248UA_Session_detachSubscription(UA_Server *server, UA_Session *session,
2249 UA_Subscription *sub, UA_Boolean releasePublishResponses);
2250
2251UA_Subscription *
2252UA_Session_getSubscriptionById(UA_Session *session,
2253 UA_UInt32 subscriptionId);
2254
2255
2256void
2257UA_Session_queuePublishReq(UA_Session *session,
2258 UA_PublishResponseEntry* entry,
2259 UA_Boolean head);
2260
2261UA_PublishResponseEntry *
2262UA_Session_dequeuePublishReq(UA_Session *session);
2263
2264#endif
2265
2266/**
2267 * Log Helper
2268 * ----------
2269 * We have to jump through some hoops to enable the use of format strings
2270 * without arguments since (pedantic) C99 does not allow variadic macros with
2271 * zero arguments. So we add a dummy argument that is not printed (%.0s is
2272 * string of length zero). */
2273
2274#define UA_LOG_SESSION_INTERNAL(LOGGER, LEVEL, SESSION, MSG, ...) \
2275 do { \
2276 int nameLen = (SESSION) ? (int)(SESSION)->sessionName.length : 0; \
2277 const char *nameStr = (SESSION) ? \
2278 (const char*)(SESSION)->sessionName.data : NULL; \
2279 UA_UInt32 chanId = ((SESSION) && (SESSION)->header.channel) ? \
2280 (SESSION)->header.channel->securityToken.channelId : 0; \
2281 UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_SESSION, \
2282 "SecureChannel %" PRIu32 " | Session \"%.*s\" | " MSG "%.0s", \
2283 chanId, nameLen, nameStr, __VA_ARGS__); \
2284 } while(0)
2285
2286#if UA_LOGLEVEL <= 100
2287# define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...) \
2288 UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, TRACE, SESSION, __VA_ARGS__, ""))
2289#else
2290# define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...)
2291#endif
2292
2293#if UA_LOGLEVEL <= 200
2294# define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...) \
2295 UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, DEBUG, SESSION, __VA_ARGS__, ""))
2296#else
2297# define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...)
2298#endif
2299
2300#if UA_LOGLEVEL <= 300
2301# define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...) \
2302 UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, INFO, SESSION, __VA_ARGS__, ""))
2303#else
2304# define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...)
2305#endif
2306
2307#if UA_LOGLEVEL <= 400
2308# define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...) \
2309 UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, WARNING, SESSION, __VA_ARGS__, ""))
2310#else
2311# define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...)
2312#endif
2313
2314#if UA_LOGLEVEL <= 500
2315# define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...) \
2316 UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, ERROR, SESSION, __VA_ARGS__, ""))
2317#else
2318# define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...)
2319#endif
2320
2321#if UA_LOGLEVEL <= 600
2322# define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...) \
2323 UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, FATAL, SESSION, __VA_ARGS__, ""))
2324#else
2325# define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...)
2326#endif
2327
2328_UA_END_DECLS
2329
2330
2331/**** amalgamated original file "/src/server/ua_subscription.h" ****/
2332
2333/* This Source Code Form is subject to the terms of the Mozilla Public
2334 * License, v. 2.0. If a copy of the MPL was not distributed with this
2335 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
2336 *
2337 * Copyright 2015-2018, 2021-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
2338 * Copyright 2015 (c) Chris Iatrou
2339 * Copyright 2015-2016 (c) Sten Grüner
2340 * Copyright 2015 (c) Oleksiy Vasylyev
2341 * Copyright 2017 (c) Florian Palm
2342 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
2343 * Copyright 2017 (c) Mattias Bornhager
2344 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
2345 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
2346 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
2347 */
2348
2349
2350
2351
2352_UA_BEGIN_DECLS
2353
2354#ifdef UA_ENABLE_SUBSCRIPTIONS
2355
2356/* MonitoredItems create Notifications. Subscriptions collect Notifications from
2357 * (several) MonitoredItems and publish them to the client.
2358 *
2359 * Notifications are put into two queues at the same time. One for the
2360 * MonitoredItem that generated the notification. Here we can remove it if the
2361 * space reserved for the MonitoredItem runs full. The second queue is the
2362 * "global" queue for all Notifications generated in a Subscription. For
2363 * publication, the notifications are taken out of the "global" queue in the
2364 * order of their creation. */
2365
2366/*****************/
2367/* Notifications */
2368/*****************/
2369
2370/* Set to the TAILQ_NEXT pointer of a notification, the sentinel that the
2371 * notification was not added to the global queue */
2372#define UA_SUBSCRIPTION_QUEUE_SENTINEL ((UA_Notification*)0x01)
2373
2374typedef struct UA_Notification {
2375 TAILQ_ENTRY(UA_Notification) localEntry; /* Notification list for the MonitoredItem */
2376 TAILQ_ENTRY(UA_Notification) globalEntry; /* Notification list for the Subscription */
2377 UA_MonitoredItem *mon; /* Always set */
2378
2379 /* The event field is used if mon->attributeId is the EventNotifier */
2380 union {
2381 UA_MonitoredItemNotification dataChange;
2382#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
2383 UA_EventFieldList event;
2384#endif
2385 } data;
2386
2387#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
2388 UA_Boolean isOverflowEvent; /* Counted manually */
2389 UA_EventFilterResult result;
2390#endif
2391} UA_Notification;
2392
2393/* Initializes and sets the sentinel pointers */
2394UA_Notification * UA_Notification_new(void);
2395
2396/* Notifications are always added to the queue of the MonitoredItem. That queue
2397 * can overflow. If Notifications are reported, they are also added to the
2398 * global queue of the Subscription. There they are picked up by the publishing
2399 * callback.
2400 *
2401 * There are two ways Notifications can be put into the global queue of the
2402 * Subscription: They are added because the MonitoringMode of the MonitoredItem
2403 * is "reporting". Or the MonitoringMode is "sampling" and a link is trigered
2404 * that puts the last Notification into the global queue. */
2405void UA_Notification_enqueueAndTrigger(UA_Server *server,
2406 UA_Notification *n);
2407
2408/* Dequeue and delete the notification */
2409void UA_Notification_delete(UA_Notification *n);
2410
2411/* A NotificationMessage contains an array of notifications.
2412 * Sent NotificationMessages are stored for the republish service. */
2413typedef struct UA_NotificationMessageEntry {
2414 TAILQ_ENTRY(UA_NotificationMessageEntry) listEntry;
2415 UA_NotificationMessage message;
2416} UA_NotificationMessageEntry;
2417
2418/* Queue Definitions */
2419typedef TAILQ_HEAD(NotificationQueue, UA_Notification) NotificationQueue;
2420typedef TAILQ_HEAD(NotificationMessageQueue, UA_NotificationMessageEntry)
2421 NotificationMessageQueue;
2422
2423/*****************/
2424/* MonitoredItem */
2425/*****************/
2426
2427/* The type of sampling for MonitoredItems depends on the sampling interval.
2428 *
2429 * >0: Cyclic callback
2430 * =0: Attached to the node. Sampling is triggered after every "write".
2431 * <0: Attached to the subscription. Triggered just before every "publish". */
2432typedef enum {
2433 UA_MONITOREDITEMSAMPLINGTYPE_NONE = 0,
2434 UA_MONITOREDITEMSAMPLINGTYPE_CYCLIC, /* Cyclic callback */
2435 UA_MONITOREDITEMSAMPLINGTYPE_EVENT, /* Attached to the node. Can be a "write
2436 * event" for DataChange MonitoredItems
2437 * with a zero sampling interval .*/
2438 UA_MONITOREDITEMSAMPLINGTYPE_PUBLISH /* Attached to the subscription */
2439} UA_MonitoredItemSamplingType;
2440
2441struct UA_MonitoredItem {
2442 UA_TimerEntry delayedFreePointers;
2443 LIST_ENTRY(UA_MonitoredItem) listEntry; /* Linked list in the Subscription */
2444 UA_Subscription *subscription; /* If NULL, then this is a Local MonitoredItem */
2445 UA_UInt32 monitoredItemId;
2446
2447 /* Status and Settings */
2448 UA_ReadValueId itemToMonitor;
2449 UA_MonitoringMode monitoringMode;
2450 UA_TimestampsToReturn timestampsToReturn;
2451 UA_Boolean registered; /* Registered in the server / Subscription */
2452 UA_DateTime triggeredUntil; /* If the MonitoringMode is SAMPLING,
2453 * triggering the MonitoredItem puts the latest
2454 * Notification into the publishing queue (of
2455 * the Subscription). In addition, the first
2456 * new sample is also published (and not just
2457 * sampled) if it occurs within the duration of
2458 * one publishing cycle after the triggering. */
2459
2460 /* If the filter is a UA_DataChangeFilter: The DataChangeFilter always
2461 * contains an absolute deadband definition. Part 8, §6.2 gives the
2462 * following formula to test for percentage deadbands:
2463 *
2464 * DataChange if (absolute value of (last cached value - current value)
2465 * > (deadbandValue/100.0) * ((high–low) of EURange)))
2466 *
2467 * So we can convert from a percentage to an absolute deadband and keep
2468 * the hot code path simple.
2469 *
2470 * TODO: Store the percentage deadband to recompute when the UARange is
2471 * changed at runtime of the MonitoredItem */
2472 UA_MonitoringParameters parameters;
2473
2474 /* Sampling */
2475 UA_MonitoredItemSamplingType samplingType;
2476 union {
2477 UA_UInt64 callbackId;
2478 UA_MonitoredItem *nodeListNext; /* Event-Based: Attached to Node */
2479 LIST_ENTRY(UA_MonitoredItem) samplingListEntry; /* Publish-interval: Linked in
2480 * Subscription */
2481 } sampling;
2482 UA_DataValue lastValue;
2483
2484 /* Triggering Links */
2485 size_t triggeringLinksSize;
2486 UA_UInt32 *triggeringLinks;
2487
2488 /* Notification Queue */
2489 NotificationQueue queue;
2490 size_t queueSize; /* This is the current size. See also the configured
2491 * (maximum) queueSize in the parameters. */
2492 size_t eventOverflows; /* Separate counter for the queue. Can at most double
2493 * the queue size */
2494};
2495
2496void UA_MonitoredItem_init(UA_MonitoredItem *mon);
2497
2498void
2499UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem);
2500
2501void
2502UA_MonitoredItem_removeOverflowInfoBits(UA_MonitoredItem *mon);
2503
2504void
2505UA_Server_registerMonitoredItem(UA_Server *server, UA_MonitoredItem *mon);
2506
2507/* Register sampling. Either by adding a repeated callback or by adding the
2508 * MonitoredItem to a linked list in the node. */
2509UA_StatusCode
2510UA_MonitoredItem_registerSampling(UA_Server *server, UA_MonitoredItem *mon);
2511
2512void
2513UA_MonitoredItem_unregisterSampling(UA_Server *server,
2514 UA_MonitoredItem *mon);
2515
2516UA_StatusCode
2517UA_MonitoredItem_setMonitoringMode(UA_Server *server, UA_MonitoredItem *mon,
2518 UA_MonitoringMode monitoringMode);
2519
2520void
2521UA_MonitoredItem_sampleCallback(UA_Server *server,
2522 UA_MonitoredItem *monitoredItem);
2523
2524UA_StatusCode
2525sampleCallbackWithValue(UA_Server *server, UA_Subscription *sub,
2526 UA_MonitoredItem *mon, UA_DataValue *value);
2527
2528UA_StatusCode
2529UA_MonitoredItem_removeLink(UA_Subscription *sub, UA_MonitoredItem *mon,
2530 UA_UInt32 linkId);
2531
2532UA_StatusCode
2533UA_MonitoredItem_addLink(UA_Subscription *sub, UA_MonitoredItem *mon,
2534 UA_UInt32 linkId);
2535
2536UA_StatusCode
2537UA_MonitoredItem_createDataChangeNotification(UA_Server *server,
2538 UA_Subscription *sub,
2539 UA_MonitoredItem *mon,
2540 const UA_DataValue *value);
2541
2542UA_StatusCode
2543UA_Event_addEventToMonitoredItem(UA_Server *server, const UA_NodeId *event,
2544 UA_MonitoredItem *mon);
2545
2546UA_StatusCode
2547UA_Event_generateEventId(UA_ByteString *generatedId);
2548
2549void
2550UA_Event_staticSelectClauseValidation(UA_Server *server,
2551 const UA_EventFilter *eventFilter,
2552 UA_StatusCode *result);
2553
2554UA_StatusCode
2555UA_Event_staticWhereClauseValidation(UA_Server *server,
2556 const UA_ContentFilter *filter,
2557 UA_ContentFilterResult *);
2558
2559/* Remove entries until mon->maxQueueSize is reached. Sets infobits for lost
2560 * data if required. */
2561void
2562UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon);
2563
2564/****************/
2565/* Subscription */
2566/****************/
2567
2568/* We use only a subset of the states defined in the standard */
2569typedef enum {
2570 /* UA_SUBSCRIPTIONSTATE_CLOSED */
2571 /* UA_SUBSCRIPTIONSTATE_CREATING */
2572 UA_SUBSCRIPTIONSTATE_NORMAL,
2573 UA_SUBSCRIPTIONSTATE_LATE,
2574 UA_SUBSCRIPTIONSTATE_KEEPALIVE
2575} UA_SubscriptionState;
2576
2577/* Subscriptions are managed in a server-wide linked list. If they are attached
2578 * to a Session, then they are additionaly in the per-Session linked-list. A
2579 * subscription is always generated for a Session. But the CloseSession Service
2580 * may keep Subscriptions intact beyond the Session lifetime. They can then be
2581 * re-bound to a new Session with the TransferSubscription Service. */
2582struct UA_Subscription {
2583 UA_TimerEntry delayedFreePointers;
2584 LIST_ENTRY(UA_Subscription) serverListEntry;
2585 /* Ordered according to the priority byte and round-robin scheduling for
2586 * late subscriptions. See ua_session.h. Only set if session != NULL. */
2587 TAILQ_ENTRY(UA_Subscription) sessionListEntry;
2588 UA_Session *session; /* May be NULL if no session is attached. */
2589 UA_UInt32 subscriptionId;
2590
2591 /* Settings */
2592 UA_UInt32 lifeTimeCount;
2593 UA_UInt32 maxKeepAliveCount;
2594 UA_Double publishingInterval; /* in ms */
2595 UA_UInt32 notificationsPerPublish;
2596 UA_Boolean publishingEnabled;
2597 UA_Byte priority;
2598
2599 /* Runtime information */
2600 UA_SubscriptionState state;
2601 UA_StatusCode statusChange; /* If set, a notification is generated and the
2602 * Subscription is deleted within
2603 * UA_Subscription_publish. */
2604 UA_UInt32 nextSequenceNumber;
2605 UA_UInt32 currentKeepAliveCount;
2606 UA_UInt32 currentLifetimeCount;
2607
2608 /* Publish Callback. Registered if id > 0. */
2609 UA_UInt64 publishCallbackId;
2610
2611 /* MonitoredItems */
2612 UA_UInt32 lastMonitoredItemId; /* increase the identifiers */
2613 LIST_HEAD(, UA_MonitoredItem) monitoredItems;
2614 UA_UInt32 monitoredItemsSize;
2615
2616 /* MonitoredItems that are sampled in every publish callback (with the
2617 * publish interval of the subscription) */
2618 LIST_HEAD(, UA_MonitoredItem) samplingMonitoredItems;
2619
2620 /* Global list of notifications from the MonitoredItems */
2621 TAILQ_HEAD(, UA_Notification) notificationQueue;
2622 UA_UInt32 notificationQueueSize; /* Total queue size */
2623 UA_UInt32 dataChangeNotifications;
2624 UA_UInt32 eventNotifications;
2625
2626 /* Retransmission Queue */
2627 NotificationMessageQueue retransmissionQueue;
2628 size_t retransmissionQueueSize;
2629
2630 /* Statistics for the server diagnostics. The fields are defined according
2631 * to the SubscriptionDiagnosticsDataType (Part 5, §12.15). */
2632#ifdef UA_ENABLE_DIAGNOSTICS
2633 UA_UInt32 modifyCount;
2634 UA_UInt32 enableCount;
2635 UA_UInt32 disableCount;
2636 UA_UInt32 republishRequestCount;
2637 UA_UInt32 republishMessageCount;
2638 UA_UInt32 transferRequestCount;
2639 UA_UInt32 transferredToAltClientCount;
2640 UA_UInt32 transferredToSameClientCount;
2641 UA_UInt32 publishRequestCount;
2642 UA_UInt32 dataChangeNotificationsCount;
2643 UA_UInt32 eventNotificationsCount;
2644 UA_UInt32 notificationsCount;
2645 UA_UInt32 latePublishRequestCount;
2646 UA_UInt32 discardedMessageCount;
2647 UA_UInt32 monitoringQueueOverflowCount;
2648 UA_UInt32 eventQueueOverFlowCount;
2649#endif
2650};
2651
2652UA_Subscription * UA_Subscription_new(void);
2653
2654void
2655UA_Subscription_delete(UA_Server *server, UA_Subscription *sub);
2656
2657UA_StatusCode
2658Subscription_registerPublishCallback(UA_Server *server,
2659 UA_Subscription *sub);
2660
2661void
2662Subscription_unregisterPublishCallback(UA_Server *server,
2663 UA_Subscription *sub);
2664
2665UA_MonitoredItem *
2666UA_Subscription_getMonitoredItem(UA_Subscription *sub,
2667 UA_UInt32 monitoredItemId);
2668
2669void
2670UA_Subscription_sampleAndPublish(UA_Server *server, UA_Subscription *sub);
2671
2672UA_Boolean
2673UA_Subscription_publishOnce(UA_Server *server, UA_Subscription *sub);
2674
2675void
2676UA_Subscription_publish(UA_Server *server, UA_Subscription *sub);
2677
2678UA_StatusCode
2679UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub,
2680 UA_UInt32 sequenceNumber);
2681
2682UA_Boolean
2683UA_Session_reachedPublishReqLimit(UA_Server *server, UA_Session *session);
2684
2685/* Forward declaration for A&C used in ua_server_internal.h" */
2686struct UA_ConditionSource;
2687typedef struct UA_ConditionSource UA_ConditionSource;
2688
2689/***********/
2690/* Helpers */
2691/***********/
2692
2693/* Evaluate content filter, Only for unit testing */
2694#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
2695UA_StatusCode
2696UA_Server_evaluateWhereClauseContentFilter(UA_Server *server, UA_Session *session,
2697 const UA_NodeId *eventNode,
2698 const UA_ContentFilter *contentFilter,
2699 UA_ContentFilterResult *contentFilterResult);
2700#endif
2701
2702/* Setting an integer value within bounds */
2703#define UA_BOUNDEDVALUE_SETWBOUNDS(BOUNDS, SRC, DST) { \
2704 if(SRC > BOUNDS.max) DST = BOUNDS.max; \
2705 else if(SRC < BOUNDS.min) DST = BOUNDS.min; \
2706 else DST = SRC; \
2707 }
2708
2709/* Logging
2710 * See a description of the tricks used in ua_session.h */
2711#define UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, LEVEL, SUB, MSG, ...) \
2712 do { \
2713 if((SUB) && (SUB)->session) { \
2714 UA_LOG_##LEVEL##_SESSION(LOGGER, (SUB)->session, \
2715 "Subscription %" PRIu32 " | " MSG "%.0s", \
2716 (SUB)->subscriptionId, __VA_ARGS__); \
2717 } else { \
2718 UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_SERVER, \
2719 "Subscription %" PRIu32 " | " MSG "%.0s", \
2720 (SUB) ? (SUB)->subscriptionId : 0, __VA_ARGS__); \
2721 } \
2722 } while(0)
2723
2724#if UA_LOGLEVEL <= 100
2725# define UA_LOG_TRACE_SUBSCRIPTION(LOGGER, SUB, ...) \
2726 UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, TRACE, SUB, __VA_ARGS__, ""))
2727#else
2728# define UA_LOG_TRACE_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
2729#endif
2730
2731#if UA_LOGLEVEL <= 200
2732# define UA_LOG_DEBUG_SUBSCRIPTION(LOGGER, SUB, ...) \
2733 UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, DEBUG, SUB, __VA_ARGS__, ""))
2734#else
2735# define UA_LOG_DEBUG_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
2736#endif
2737
2738#if UA_LOGLEVEL <= 300
2739# define UA_LOG_INFO_SUBSCRIPTION(LOGGER, SUB, ...) \
2740 UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, INFO, SUB, __VA_ARGS__, ""))
2741#else
2742# define UA_LOG_INFO_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
2743#endif
2744
2745#if UA_LOGLEVEL <= 400
2746# define UA_LOG_WARNING_SUBSCRIPTION(LOGGER, SUB, ...) \
2747 UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, WARNING, SUB, __VA_ARGS__, ""))
2748#else
2749# define UA_LOG_WARNING_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
2750#endif
2751
2752#if UA_LOGLEVEL <= 500
2753# define UA_LOG_ERROR_SUBSCRIPTION(LOGGER, SUB, ...) \
2754 UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, ERROR, SUB, __VA_ARGS__, ""))
2755#else
2756# define UA_LOG_ERROR_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
2757#endif
2758
2759#if UA_LOGLEVEL <= 600
2760# define UA_LOG_FATAL_SUBSCRIPTION(LOGGER, SUB, ...) \
2761 UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, FATAL, SUB, __VA_ARGS__, ""))
2762#else
2763# define UA_LOG_FATAL_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0)
2764#endif
2765
2766#endif /* UA_ENABLE_SUBSCRIPTIONS */
2767
2768_UA_END_DECLS
2769
2770
2771/**** amalgamated original file "/src/pubsub/ua_pubsub_networkmessage.h" ****/
2772
2773/* This Source Code Form is subject to the terms of the Mozilla Public
2774 * License, v. 2.0. If a copy of the MPL was not distributed with this
2775 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
2776 *
2777 * Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Tino Bischoff)
2778 * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
2779 */
2780
2781
2782
2783_UA_BEGIN_DECLS
2784
2785/* DataSet Payload Header */
2786typedef struct {
2787 UA_Byte count;
2788 UA_UInt16* dataSetWriterIds;
2789} UA_DataSetPayloadHeader;
2790
2791/* FieldEncoding Enum */
2792typedef enum {
2793 UA_FIELDENCODING_VARIANT = 0,
2794 UA_FIELDENCODING_RAWDATA = 1,
2795 UA_FIELDENCODING_DATAVALUE = 2,
2796 UA_FIELDENCODING_UNKNOWN = 3
2797} UA_FieldEncoding;
2798
2799/* DataSetMessage Type */
2800typedef enum {
2801 UA_DATASETMESSAGE_DATAKEYFRAME = 0,
2802 UA_DATASETMESSAGE_DATADELTAFRAME = 1,
2803 UA_DATASETMESSAGE_EVENT = 2,
2804 UA_DATASETMESSAGE_KEEPALIVE = 3
2805} UA_DataSetMessageType;
2806
2807/* DataSetMessage Header */
2808typedef struct {
2809 UA_Boolean dataSetMessageValid;
2810 UA_FieldEncoding fieldEncoding;
2811 UA_Boolean dataSetMessageSequenceNrEnabled;
2812 UA_Boolean timestampEnabled;
2813 UA_Boolean statusEnabled;
2814 UA_Boolean configVersionMajorVersionEnabled;
2815 UA_Boolean configVersionMinorVersionEnabled;
2816 UA_DataSetMessageType dataSetMessageType;
2817 UA_Boolean picoSecondsIncluded;
2818 UA_UInt16 dataSetMessageSequenceNr;
2819 UA_UtcTime timestamp;
2820 UA_UInt16 picoSeconds;
2821 UA_UInt16 status;
2822 UA_UInt32 configVersionMajorVersion;
2823 UA_UInt32 configVersionMinorVersion;
2824} UA_DataSetMessageHeader;
2825
2826/**
2827 * DataSetMessage
2828 * ^^^^^^^^^^^^^^ */
2829
2830typedef struct {
2831 UA_UInt16 fieldCount;
2832 UA_DataValue* dataSetFields;
2833 UA_ByteString rawFields;
2834 /* Json keys for the dataSetFields: TODO: own dataSetMessageType for json? */
2835 UA_String* fieldNames;
2836} UA_DataSetMessage_DataKeyFrameData;
2837
2838typedef struct {
2839 UA_UInt16 fieldIndex;
2840 UA_DataValue fieldValue;
2841} UA_DataSetMessage_DeltaFrameField;
2842
2843typedef struct {
2844 UA_UInt16 fieldCount;
2845 UA_DataSetMessage_DeltaFrameField* deltaFrameFields;
2846} UA_DataSetMessage_DataDeltaFrameData;
2847
2848typedef struct {
2849 UA_DataSetMessageHeader header;
2850 union {
2851 UA_DataSetMessage_DataKeyFrameData keyFrameData;
2852 UA_DataSetMessage_DataDeltaFrameData deltaFrameData;
2853 } data;
2854} UA_DataSetMessage;
2855
2856typedef struct {
2857 UA_UInt16* sizes;
2858 UA_DataSetMessage* dataSetMessages;
2859} UA_DataSetPayload;
2860
2861typedef enum {
2862 UA_PUBLISHERDATATYPE_BYTE = 0,
2863 UA_PUBLISHERDATATYPE_UINT16 = 1,
2864 UA_PUBLISHERDATATYPE_UINT32 = 2,
2865 UA_PUBLISHERDATATYPE_UINT64 = 3,
2866 UA_PUBLISHERDATATYPE_STRING = 4
2867} UA_PublisherIdDatatype;
2868
2869typedef enum {
2870 UA_NETWORKMESSAGE_DATASET = 0,
2871 UA_NETWORKMESSAGE_DISCOVERY_REQUEST = 1,
2872 UA_NETWORKMESSAGE_DISCOVERY_RESPONSE = 2
2873} UA_NetworkMessageType;
2874
2875/**
2876 * UA_NetworkMessageGroupHeader
2877 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
2878typedef struct {
2879 UA_Boolean writerGroupIdEnabled;
2880 UA_Boolean groupVersionEnabled;
2881 UA_Boolean networkMessageNumberEnabled;
2882 UA_Boolean sequenceNumberEnabled;
2883 UA_UInt16 writerGroupId;
2884 UA_UInt32 groupVersion; // spec: type "VersionTime"
2885 UA_UInt16 networkMessageNumber;
2886 UA_UInt16 sequenceNumber;
2887} UA_NetworkMessageGroupHeader;
2888
2889/**
2890 * UA_NetworkMessageSecurityHeader
2891 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
2892typedef struct {
2893 UA_Boolean networkMessageSigned;
2894 UA_Boolean networkMessageEncrypted;
2895 UA_Boolean securityFooterEnabled;
2896 UA_Boolean forceKeyReset;
2897 UA_UInt32 securityTokenId; // spec: IntegerId
2898 UA_ByteString messageNonce;
2899 UA_UInt16 securityFooterSize;
2900} UA_NetworkMessageSecurityHeader;
2901
2902/**
2903 * UA_NetworkMessage
2904 * ^^^^^^^^^^^^^^^^^ */
2905typedef struct {
2906 UA_Byte version;
2907 UA_Boolean messageIdEnabled;
2908 UA_String messageId; /* For Json NetworkMessage */
2909 UA_Boolean publisherIdEnabled;
2910 UA_Boolean groupHeaderEnabled;
2911 UA_Boolean payloadHeaderEnabled;
2912 UA_PublisherIdDatatype publisherIdType;
2913 UA_Boolean dataSetClassIdEnabled;
2914 UA_Boolean securityEnabled;
2915 UA_Boolean timestampEnabled;
2916 UA_Boolean picosecondsEnabled;
2917 UA_Boolean chunkMessage;
2918 UA_Boolean promotedFieldsEnabled;
2919 UA_NetworkMessageType networkMessageType;
2920 union {
2921 UA_Byte publisherIdByte;
2922 UA_UInt16 publisherIdUInt16;
2923 UA_UInt32 publisherIdUInt32;
2924 UA_UInt64 publisherIdUInt64;
2925 UA_Guid publisherIdGuid;
2926 UA_String publisherIdString;
2927 } publisherId;
2928 UA_Guid dataSetClassId;
2929
2930 UA_NetworkMessageGroupHeader groupHeader;
2931
2932 union {
2933 UA_DataSetPayloadHeader dataSetPayloadHeader;
2934 } payloadHeader;
2935
2936 UA_DateTime timestamp;
2937 UA_UInt16 picoseconds;
2938 UA_UInt16 promotedFieldsSize;
2939 UA_Variant* promotedFields; /* BaseDataType */
2940
2941 UA_NetworkMessageSecurityHeader securityHeader;
2942
2943 union {
2944 UA_DataSetPayload dataSetPayload;
2945 } payload;
2946
2947 UA_ByteString securityFooter;
2948} UA_NetworkMessage;
2949
2950/**********************************************/
2951/* Network Message Offsets */
2952/**********************************************/
2953
2954/* Offsets for buffered messages in the PubSub fast path. */
2955typedef enum {
2956 UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER,
2957 UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER,
2958 UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING,
2959 UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS,
2960 UA_PUBSUB_OFFSETTYPE_TIMESTAMP, /* source pointer */
2961 UA_PUBSUB_OFFSETTYPE_TIMESTAMP_NOW, /* no source */
2962 UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE,
2963 UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT,
2964 UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW,
2965 /* For subscriber RT */
2966 UA_PUBSUB_OFFSETTYPE_PUBLISHERID,
2967 UA_PUBSUB_OFFSETTYPE_WRITERGROUPID,
2968 UA_PUBSUB_OFFSETTYPE_DATASETWRITERID
2969 /* Add more offset types as needed */
2970} UA_NetworkMessageOffsetType;
2971
2972typedef struct {
2973 UA_NetworkMessageOffsetType contentType;
2974 union {
2975 struct {
2976 UA_DataValue *value;
2977 size_t valueBinarySize;
2978 } value;
2979 UA_DateTime *timestamp;
2980 } offsetData;
2981 size_t offset;
2982} UA_NetworkMessageOffset;
2983
2984typedef struct {
2985 UA_ByteString buffer; /* The precomputed message buffer */
2986 UA_NetworkMessageOffset *offsets; /* Offsets for changes in the message buffer */
2987 size_t offsetsSize;
2988 UA_Boolean RTsubscriberEnabled; /* Addtional offsets computation like publisherId, WGId if this bool enabled */
2989 UA_NetworkMessage *nm; /* The precomputed NetworkMessage for subscriber */
2990 size_t rawMessageLength;
2991} UA_NetworkMessageOffsetBuffer;
2992
2993void
2994UA_NetworkMessageOffsetBuffer_clear(UA_NetworkMessageOffsetBuffer *ob);
2995
2996/**
2997 * DataSetMessage
2998 * ^^^^^^^^^^^^^^ */
2999
3000UA_StatusCode
3001UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src,
3002 UA_Byte **bufPos, const UA_Byte *bufEnd);
3003
3004UA_StatusCode
3005UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
3006 UA_DataSetMessageHeader* dst);
3007
3008size_t
3009UA_DataSetMessageHeader_calcSizeBinary(const UA_DataSetMessageHeader* p);
3010
3011UA_StatusCode
3012UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
3013 const UA_Byte *bufEnd);
3014
3015UA_StatusCode
3016UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
3017 UA_DataSetMessage* dst, UA_UInt16 dsmSize);
3018
3019size_t
3020UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer,
3021 size_t currentOffset);
3022
3023void UA_DataSetMessage_clear(const UA_DataSetMessage* p);
3024
3025/**
3026 * NetworkMessage
3027 * ^^^^^^^^^^^^^^ */
3028
3029UA_StatusCode
3030UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer);
3031
3032UA_StatusCode
3033UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
3034 const UA_ByteString *src, size_t *bufferPosition);
3035
3036
3037/**
3038 * NetworkMessage Encoding
3039 * ^^^^^^^^^^^^^^^^^^^^^^^ */
3040
3041/* If dataToEncryptStart not-NULL, then it will be set to the start-position of
3042 * the payload in the buffer. */
3043UA_StatusCode
3044UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src,
3045 UA_Byte **bufPos, const UA_Byte *bufEnd,
3046 UA_Byte **dataToEncryptStart);
3047
3048UA_StatusCode
3049UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage* src,
3050 UA_Byte **bufPos, const UA_Byte *bufEnd);
3051
3052UA_StatusCode
3053UA_NetworkMessage_encodePayload(const UA_NetworkMessage* src,
3054 UA_Byte **bufPos, const UA_Byte *bufEnd);
3055
3056UA_StatusCode
3057UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src,
3058 UA_Byte **bufPos, const UA_Byte *bufEnd);
3059
3060/**
3061 * NetworkMessage Decoding
3062 * ^^^^^^^^^^^^^^^^^^^^^^^ */
3063
3064UA_StatusCode
3065UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst);
3066
3067UA_StatusCode
3068UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst);
3069
3070UA_StatusCode
3071UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst);
3072
3073UA_StatusCode
3074UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
3075 UA_NetworkMessage* dst);
3076
3077
3078UA_StatusCode
3079UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst);
3080
3081size_t
3082UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p,
3083 UA_NetworkMessageOffsetBuffer *offsetBuffer);
3084
3085#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
3086
3087UA_StatusCode
3088UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode securityMode,
3089 UA_PubSubSecurityPolicy *policy, void *policyContext,
3090 UA_Byte *messageStart, UA_Byte *encryptStart,
3091 UA_Byte *sigStart);
3092#endif
3093
3094void
3095UA_NetworkMessage_clear(UA_NetworkMessage* p);
3096
3097#ifdef UA_ENABLE_JSON_ENCODING
3098UA_StatusCode
3099UA_NetworkMessage_encodeJson(const UA_NetworkMessage *src,
3100 UA_Byte **bufPos, const UA_Byte **bufEnd, UA_String *namespaces,
3101 size_t namespaceSize, UA_String *serverUris,
3102 size_t serverUriSize, UA_Boolean useReversible);
3103
3104size_t
3105UA_NetworkMessage_calcSizeJson(const UA_NetworkMessage *src,
3106 UA_String *namespaces, size_t namespaceSize,
3107 UA_String *serverUris, size_t serverUriSize,
3108 UA_Boolean useReversible);
3109
3110UA_StatusCode UA_NetworkMessage_decodeJson(UA_NetworkMessage *dst, const UA_ByteString *src);
3111#endif
3112
3113_UA_END_DECLS
3114
3115
3116/**** amalgamated original file "/src/pubsub/ua_pubsub.h" ****/
3117
3118/* This Source Code Form is subject to the terms of the Mozilla Public
3119 * License, v. 2.0. If a copy of the MPL was not distributed with this
3120 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
3121 *
3122 * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
3123 * Copyright (c) 2019 Kalycito Infotech Private Limited
3124 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
3125 * Copyright (c) 2020 Thomas Fischer, Siemens AG
3126 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
3127 */
3128
3129
3130
3131
3132/* The public configuration structs are defined in include/ua_plugin_pubsub.h */
3133
3134_UA_BEGIN_DECLS
3135
3136#ifdef UA_ENABLE_PUBSUB
3137
3138struct UA_WriterGroup;
3139typedef struct UA_WriterGroup UA_WriterGroup;
3140
3141struct UA_ReaderGroup;
3142typedef struct UA_ReaderGroup UA_ReaderGroup;
3143
3144/**********************************************/
3145/* PublishedDataSet */
3146/**********************************************/
3147
3148typedef struct UA_PublishedDataSet {
3149 UA_PublishedDataSetConfig config;
3150 UA_DataSetMetaDataType dataSetMetaData;
3151 TAILQ_HEAD(UA_ListOfDataSetField, UA_DataSetField) fields;
3152 UA_NodeId identifier;
3153 UA_UInt16 fieldSize;
3154 UA_UInt16 promotedFieldsCount;
3155 UA_UInt16 configurationFreezeCounter;
3156 TAILQ_ENTRY(UA_PublishedDataSet) listEntry;
3157 UA_Boolean configurationFrozen;
3158} UA_PublishedDataSet;
3159
3160UA_StatusCode
3161UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src,
3162 UA_PublishedDataSetConfig *dst);
3163
3164UA_PublishedDataSet *
3165UA_PublishedDataSet_findPDSbyId(UA_Server *server, UA_NodeId identifier);
3166
3167void
3168UA_PublishedDataSet_clear(UA_Server *server,
3169 UA_PublishedDataSet *publishedDataSet);
3170
3171/**********************************************/
3172/* Connection */
3173/**********************************************/
3174
3175typedef struct UA_PubSubConnection {
3176 UA_PubSubComponentEnumType componentType;
3177 UA_PubSubConnectionConfig *config;
3178 UA_PubSubChannel *channel;
3179 UA_NodeId identifier;
3180 LIST_HEAD(UA_ListOfWriterGroup, UA_WriterGroup) writerGroups;
3181 size_t writerGroupsSize;
3182 LIST_HEAD(UA_ListOfPubSubReaderGroup, UA_ReaderGroup) readerGroups;
3183 size_t readerGroupsSize;
3184 TAILQ_ENTRY(UA_PubSubConnection) listEntry;
3185 UA_UInt16 configurationFreezeCounter;
3186 UA_Boolean isRegistered; /* Subscriber requires connection channel regist */
3187 UA_Boolean configurationFrozen;
3188} UA_PubSubConnection;
3189
3190UA_StatusCode
3191UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src,
3192 UA_PubSubConnectionConfig *dst);
3193
3194UA_PubSubConnection *
3195UA_PubSubConnection_findConnectionbyId(UA_Server *server,
3196 UA_NodeId connectionIdentifier);
3197
3198void
3199UA_PubSubConnectionConfig_clear(UA_PubSubConnectionConfig *connectionConfig);
3200
3201void
3202UA_PubSubConnection_clear(UA_Server *server, UA_PubSubConnection *connection);
3203
3204/* Register channel for given connectionIdentifier */
3205UA_StatusCode
3206UA_PubSubConnection_regist(UA_Server *server, UA_NodeId *connectionIdentifier);
3207
3208/* Process Network Message for a ReaderGroup. But we the ReaderGroup needs to be
3209 * identified first. */
3210UA_StatusCode
3211UA_Server_processNetworkMessage(UA_Server *server,
3212 UA_PubSubConnection *connection,
3213 UA_NetworkMessage *msg);
3214
3215/**********************************************/
3216/* DataSetWriter */
3217/**********************************************/
3218
3219#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
3220typedef struct UA_DataSetWriterSample {
3221 UA_Boolean valueChanged;
3222 UA_DataValue value;
3223} UA_DataSetWriterSample;
3224#endif
3225
3226typedef struct UA_DataSetWriter {
3227 UA_PubSubComponentEnumType componentType;
3228 UA_DataSetWriterConfig config;
3229 LIST_ENTRY(UA_DataSetWriter) listEntry;
3230 UA_NodeId identifier;
3231 UA_NodeId linkedWriterGroup;
3232 UA_NodeId connectedDataSet;
3233 UA_ConfigurationVersionDataType connectedDataSetVersion;
3234 UA_PubSubState state;
3235#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
3236 UA_UInt16 deltaFrameCounter; /* count of sent deltaFrames */
3237 size_t lastSamplesCount;
3238 UA_DataSetWriterSample *lastSamples;
3239#endif
3240 UA_UInt16 actualDataSetMessageSequenceCount;
3241 UA_Boolean configurationFrozen;
3242} UA_DataSetWriter;
3243
3244UA_StatusCode
3245UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src,
3246 UA_DataSetWriterConfig *dst);
3247
3248UA_DataSetWriter *
3249UA_DataSetWriter_findDSWbyId(UA_Server *server, UA_NodeId identifier);
3250
3251UA_StatusCode
3252UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state,
3253 UA_DataSetWriter *dataSetWriter);
3254
3255UA_StatusCode
3256UA_DataSetWriter_generateDataSetMessage(UA_Server *server,
3257 UA_DataSetMessage *dataSetMessage,
3258 UA_DataSetWriter *dataSetWriter);
3259
3260UA_StatusCode
3261UA_DataSetWriter_remove(UA_Server *server, UA_WriterGroup *linkedWriterGroup,
3262 UA_DataSetWriter *dataSetWriter);
3263
3264/**********************************************/
3265/* WriterGroup */
3266/**********************************************/
3267
3268struct UA_WriterGroup {
3269 UA_PubSubComponentEnumType componentType;
3270 UA_WriterGroupConfig config;
3271 LIST_ENTRY(UA_WriterGroup) listEntry;
3272 UA_NodeId identifier;
3273 UA_PubSubConnection *linkedConnection;
3274 LIST_HEAD(UA_ListOfDataSetWriter, UA_DataSetWriter) writers;
3275 UA_UInt32 writersCount;
3276 UA_UInt64 publishCallbackId;
3277 UA_Boolean publishCallbackIsRegistered;
3278 UA_PubSubState state;
3279 UA_NetworkMessageOffsetBuffer bufferedMessage;
3280 UA_UInt16 sequenceNumber; /* Increased after every succressuly sent message */
3281 UA_Boolean configurationFrozen;
3282
3283#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
3284 UA_UInt32 securityTokenId;
3285 UA_UInt32 nonceSequenceNumber; /* To be part of the MessageNonce */
3286 void *securityPolicyContext;
3287#endif
3288};
3289
3290UA_StatusCode
3291UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src,
3292 UA_WriterGroupConfig *dst);
3293
3294UA_WriterGroup *
3295UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier);
3296
3297UA_StatusCode
3298UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
3299 UA_WriterGroup *writerGroup);
3300
3301/**********************************************/
3302/* DataSetField */
3303/**********************************************/
3304
3305typedef struct UA_DataSetField {
3306 UA_DataSetFieldConfig config;
3307 TAILQ_ENTRY(UA_DataSetField) listEntry;
3308 UA_NodeId identifier;
3309 UA_NodeId publishedDataSet; /* parent pds */
3310 UA_FieldMetaData fieldMetaData; /* contains the dataSetFieldId */
3311 UA_UInt64 sampleCallbackId;
3312 UA_Boolean sampleCallbackIsRegistered;
3313 UA_Boolean configurationFrozen;
3314} UA_DataSetField;
3315
3316UA_StatusCode
3317UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src,
3318 UA_DataSetFieldConfig *dst);
3319
3320UA_DataSetField *
3321UA_DataSetField_findDSFbyId(UA_Server *server, UA_NodeId identifier);
3322
3323/**********************************************/
3324/* DataSetReader */
3325/**********************************************/
3326
3327/* DataSetReader Type definition */
3328typedef struct UA_DataSetReader {
3329 UA_PubSubComponentEnumType componentType;
3330 UA_DataSetReaderConfig config;
3331 UA_NodeId identifier;
3332 UA_NodeId linkedReaderGroup;
3333 LIST_ENTRY(UA_DataSetReader) listEntry;
3334
3335 UA_PubSubState state; /* non std */
3336 UA_Boolean configurationFrozen;
3337 UA_NetworkMessageOffsetBuffer bufferedMessage;
3338
3339#ifdef UA_ENABLE_PUBSUB_MONITORING
3340 /* MessageReceiveTimeout handling */
3341 UA_ServerCallback msgRcvTimeoutTimerCallback;
3342 UA_UInt64 msgRcvTimeoutTimerId;
3343 UA_Boolean msgRcvTimeoutTimerRunning;
3344#endif
3345} UA_DataSetReader;
3346
3347/* Process Network Message using DataSetReader */
3348void
3349UA_DataSetReader_process(UA_Server *server,
3350 UA_ReaderGroup *readerGroup,
3351 UA_DataSetReader *dataSetReader,
3352 UA_DataSetMessage *dataSetMsg);
3353
3354/* Copy the configuration of DataSetReader */
3355UA_StatusCode UA_DataSetReaderConfig_copy(const UA_DataSetReaderConfig *src,
3356 UA_DataSetReaderConfig *dst);
3357
3358/* Clear the configuration of a DataSetReader */
3359void UA_DataSetReaderConfig_clear(UA_DataSetReaderConfig *cfg);
3360
3361/* Copy the configuration of Target Variables */
3362UA_StatusCode UA_TargetVariables_copy(const UA_TargetVariables *src,
3363 UA_TargetVariables *dst);
3364
3365/* Clear the Target Variables configuration */
3366void UA_TargetVariables_clear(UA_TargetVariables *subscribedDataSetTarget);
3367
3368/* Copy the configuration of Field Target Variables */
3369UA_StatusCode UA_FieldTargetVariable_copy(const UA_FieldTargetVariable *src,
3370 UA_FieldTargetVariable *dst);
3371
3372UA_StatusCode
3373UA_DataSetReader_setPubSubState(UA_Server *server, UA_PubSubState state,
3374 UA_DataSetReader *dataSetReader);
3375
3376#ifdef UA_ENABLE_PUBSUB_MONITORING
3377/* Check if DataSetReader has a message receive timeout */
3378void
3379UA_DataSetReader_checkMessageReceiveTimeout(UA_Server *server,
3380 UA_DataSetReader *dataSetReader);
3381
3382/* DataSetReader MessageReceiveTimeout callback for generic PubSub component
3383 * timeout handling */
3384void
3385UA_DataSetReader_handleMessageReceiveTimeout(UA_Server *server,
3386 void *dataSetReader);
3387#endif /* UA_ENABLE_PUBSUB_MONITORING */
3388
3389UA_StatusCode
3390UA_DataSetReader_generateNetworkMessage(UA_PubSubConnection *pubSubConnection,
3391 UA_DataSetReader *dataSetReader,
3392 UA_DataSetMessage *dsm, UA_UInt16 *writerId,
3393 UA_Byte dsmCount, UA_NetworkMessage *nm);
3394
3395UA_StatusCode
3396UA_DataSetReader_generateDataSetMessage(UA_Server *server,
3397 UA_DataSetMessage *dataSetMessage,
3398 UA_DataSetReader *dataSetReader);
3399
3400/**********************************************/
3401/* ReaderGroup */
3402/**********************************************/
3403
3404struct UA_ReaderGroup {
3405 UA_PubSubComponentEnumType componentType;
3406 UA_ReaderGroupConfig config;
3407 UA_NodeId identifier;
3408 UA_NodeId linkedConnection;
3409 LIST_ENTRY(UA_ReaderGroup) listEntry;
3410 LIST_HEAD(UA_ListOfPubSubDataSetReader, UA_DataSetReader) readers;
3411 /* for simplified information access */
3412 UA_UInt32 readersCount;
3413 UA_UInt64 subscribeCallbackId;
3414 UA_PubSubState state;
3415 UA_Boolean configurationFrozen;
3416
3417#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
3418 UA_UInt32 securityTokenId;
3419 UA_UInt32 nonceSequenceNumber; /* To be part of the MessageNonce */
3420 void *securityPolicyContext;
3421#endif
3422};
3423
3424UA_StatusCode
3425UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src,
3426 UA_ReaderGroupConfig *dst);
3427
3428/* Prototypes for internal util functions - some functions maybe removed later
3429 * (currently moved from public to internal) */
3430UA_ReaderGroup *
3431UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier);
3432
3433UA_DataSetReader *
3434UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier);
3435
3436UA_StatusCode
3437UA_ReaderGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
3438 UA_ReaderGroup *readerGroup);
3439
3440/*********************************************************/
3441/* PublishValues handling */
3442/*********************************************************/
3443
3444UA_StatusCode
3445UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup);
3446
3447void
3448UA_WriterGroup_publishCallback(UA_Server *server, UA_WriterGroup *writerGroup);
3449
3450/*********************************************************/
3451/* SubscribeValues handling */
3452/*********************************************************/
3453
3454UA_StatusCode
3455UA_ReaderGroup_addSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup);
3456
3457void
3458UA_ReaderGroup_removeSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup);
3459
3460void
3461UA_ReaderGroup_subscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup);
3462
3463/*********************************************************/
3464/* Reading Message handling */
3465/*********************************************************/
3466
3467#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
3468UA_StatusCode
3469verifyAndDecrypt(const UA_Logger *logger, UA_ByteString *buffer,
3470 const size_t *currentPosition, const UA_NetworkMessage *nm,
3471 UA_Boolean doValidate, UA_Boolean doDecrypt,
3472 void *channelContext, UA_PubSubSecurityPolicy *securityPolicy);
3473
3474UA_StatusCode
3475verifyAndDecryptNetworkMessage(const UA_Logger *logger, UA_ByteString *buffer,
3476 size_t *currentPosition, UA_NetworkMessage *nm,
3477 UA_ReaderGroup *readerGroup);
3478#endif
3479
3480/* Takes a value (and not a pointer) to the buffer. The original buffer is
3481 const. Internally we may adjust the length during decryption. */
3482UA_StatusCode
3483decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos,
3484 UA_NetworkMessage *nm, UA_PubSubConnection *connection);
3485
3486UA_StatusCode
3487receiveBufferedNetworkMessage(UA_Server *server, UA_ReaderGroup *readerGroup,
3488 UA_PubSubConnection *connection);
3489
3490#endif /* UA_ENABLE_PUBSUB */
3491
3492_UA_END_DECLS
3493
3494
3495/**** amalgamated original file "/src/pubsub/ua_pubsub_manager.h" ****/
3496
3497/* This Source Code Form is subject to the terms of the Mozilla Public
3498 * License, v. 2.0. If a copy of the MPL was not distributed with this
3499 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
3500 *
3501 * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
3502 */
3503
3504
3505
3506
3507_UA_BEGIN_DECLS
3508
3509#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
3510
3511typedef struct UA_PubSubManager {
3512 /* Connections and PublishedDataSets can exist alone (own lifecycle) -> top
3513 * level components */
3514 size_t connectionsSize;
3515 TAILQ_HEAD(UA_ListOfPubSubConnection, UA_PubSubConnection) connections;
3516
3517 size_t publishedDataSetsSize;
3518 TAILQ_HEAD(UA_ListOfPublishedDataSet, UA_PublishedDataSet) publishedDataSets;
3519
3520#ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL
3521 UA_UInt32 uniqueIdCount;
3522#endif
3523} UA_PubSubManager;
3524
3525void
3526UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager);
3527
3528#ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL
3529void
3530UA_PubSubManager_generateUniqueNodeId(UA_PubSubManager *psm, UA_NodeId *nodeId);
3531#endif
3532
3533UA_Guid
3534UA_PubSubManager_generateUniqueGuid(UA_Server *server);
3535
3536UA_UInt32
3537UA_PubSubConfigurationVersionTimeDifference(void);
3538
3539/***********************************/
3540/* PubSub Jobs abstraction */
3541/***********************************/
3542UA_StatusCode
3543UA_PubSubManager_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
3544 void *data, UA_Double interval_ms, UA_DateTime *baseTime,
3545 UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId);
3546UA_StatusCode
3547UA_PubSubManager_changeRepeatedCallback(UA_Server *server, UA_UInt64 callbackId,
3548 UA_Double interval_ms, UA_DateTime *baseTime,
3549 UA_TimerPolicy timerPolicy);
3550void
3551UA_PubSubManager_removeRepeatedPubSubCallback(UA_Server *server, UA_UInt64 callbackId);
3552
3553/*************************************************/
3554/* PubSub component monitoring */
3555/*************************************************/
3556
3557#ifdef UA_ENABLE_PUBSUB_MONITORING
3558
3559UA_StatusCode
3560UA_PubSubManager_setDefaultMonitoringCallbacks(UA_PubSubMonitoringInterface *monitoringInterface);
3561
3562#endif /* UA_ENABLE_PUBSUB_MONITORING */
3563
3564#endif /* UA_ENABLE_PUBSUB */
3565
3566_UA_END_DECLS
3567
3568
3569/**** amalgamated original file "/src/pubsub/ua_pubsub_ns0.h" ****/
3570
3571/* This Source Code Form is subject to the terms of the Mozilla Public
3572 * License, v. 2.0. If a copy of the MPL was not distributed with this
3573 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
3574 *
3575 * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
3576 * Copyright (c) 2019 Kalycito Infotech Private Limited
3577 */
3578
3579#ifndef UA_PUBSUB_NS0_H_
3580#define UA_PUBSUB_NS0_H_
3581
3582
3583_UA_BEGIN_DECLS
3584
3585#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL /* conditional compilation */
3586
3587UA_StatusCode
3588UA_Server_initPubSubNS0(UA_Server *server);
3589
3590UA_StatusCode
3591addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection);
3592
3593UA_StatusCode
3594removePubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection);
3595
3596UA_StatusCode
3597addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup);
3598
3599UA_StatusCode
3600addReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup);
3601
3602UA_StatusCode
3603removeGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup);
3604
3605UA_StatusCode
3606addDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWriter);
3607
3608UA_StatusCode
3609removeDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWriter);
3610
3611UA_StatusCode
3612addPublishedDataItemsRepresentation(UA_Server *server, UA_PublishedDataSet *publishedDataSet);
3613
3614UA_StatusCode
3615removePublishedDataSetRepresentation(UA_Server *server, UA_PublishedDataSet *publishedDataSet);
3616
3617UA_StatusCode
3618addDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReader);
3619
3620UA_StatusCode
3621removeDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReader);
3622
3623UA_StatusCode
3624removeReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup);
3625
3626#endif /* UA_ENABLE_PUBSUB_INFORMATIONMODEL */
3627
3628_UA_END_DECLS
3629
3630#endif /* UA_PUBSUB_NS0_H_ */
3631
3632/**** amalgamated original file "/src/server/ua_server_async.h" ****/
3633
3634/* This Source Code Form is subject to the terms of the Mozilla Public
3635 * License, v. 2.0. If a copy of the MPL was not distributed with this
3636 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
3637 *
3638 * Copyright 2019 (c) Fraunhofer IOSB (Author: Klaus Schick)
3639 * based on
3640 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
3641 * Copyright 2014, 2017 (c) Florian Palm
3642 * Copyright 2015 (c) Sten Grüner
3643 * Copyright 2015 (c) Oleksiy Vasylyev
3644 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
3645 */
3646
3647
3648
3649
3650_UA_BEGIN_DECLS
3651
3652#if UA_MULTITHREADING >= 100
3653
3654struct UA_AsyncResponse;
3655typedef struct UA_AsyncResponse UA_AsyncResponse;
3656
3657/* A single operation (of a larger request) */
3658typedef struct UA_AsyncOperation {
3659 TAILQ_ENTRY(UA_AsyncOperation) pointers;
3660 UA_CallMethodRequest request;
3661 UA_CallMethodResult response;
3662 size_t index; /* Index of the operation in the array of ops in
3663 * request/response */
3664 UA_AsyncResponse *parent; /* Always non-NULL. The parent is only removed
3665 * when its operations are removed */
3666} UA_AsyncOperation;
3667
3668struct UA_AsyncResponse {
3669 TAILQ_ENTRY(UA_AsyncResponse) pointers; /* Insert new at the end */
3670 UA_UInt32 requestId;
3671 UA_NodeId sessionId;
3672 UA_UInt32 requestHandle;
3673 UA_DateTime timeout;
3674 UA_AsyncOperationType operationType;
3675 union {
3676 UA_CallResponse callResponse;
3677 UA_ReadResponse readResponse;
3678 UA_WriteResponse writeResponse;
3679 } response;
3680 UA_UInt32 opCountdown; /* Counter for outstanding operations. The AR can
3681 * only be deleted when all have returned. */
3682};
3683
3684typedef TAILQ_HEAD(UA_AsyncOperationQueue, UA_AsyncOperation) UA_AsyncOperationQueue;
3685
3686typedef struct {
3687 /* Requests / Responses */
3688 TAILQ_HEAD(, UA_AsyncResponse) asyncResponses;
3689 size_t asyncResponsesCount;
3690
3691 /* Operations for the workers. The queues are all FIFO: Put in at the tail,
3692 * take out at the head.*/
3693 UA_Lock queueLock;
3694 UA_AsyncOperationQueue newQueue; /* New operations for the workers */
3695 UA_AsyncOperationQueue dispatchedQueue; /* Operations taken by a worker. When a result is
3696 * returned, we search for the op here to see if it
3697 * is still "alive" (not timed out). */
3698 UA_AsyncOperationQueue resultQueue; /* Results to be integrated */
3699 size_t opsCount; /* How many operations are transient (in one of the three queues)? */
3700
3701 UA_UInt64 checkTimeoutCallbackId; /* Registered repeated callbacks */
3702} UA_AsyncManager;
3703
3704void UA_AsyncManager_init(UA_AsyncManager *am, UA_Server *server);
3705void UA_AsyncManager_clear(UA_AsyncManager *am, UA_Server *server);
3706
3707UA_StatusCode
3708UA_AsyncManager_createAsyncResponse(UA_AsyncManager *am, UA_Server *server,
3709 const UA_NodeId *sessionId,
3710 const UA_UInt32 requestId,
3711 const UA_UInt32 requestHandle,
3712 const UA_AsyncOperationType operationType,
3713 UA_AsyncResponse **outAr);
3714
3715/* Only remove the AsyncResponse when the operation count is zero */
3716void
3717UA_AsyncManager_removeAsyncResponse(UA_AsyncManager *am, UA_AsyncResponse *ar);
3718
3719UA_StatusCode
3720UA_AsyncManager_createAsyncOp(UA_AsyncManager *am, UA_Server *server,
3721 UA_AsyncResponse *ar, size_t opIndex,
3722 const UA_CallMethodRequest *opRequest);
3723
3724typedef void (*UA_AsyncServiceOperation)(UA_Server *server, UA_Session *session,
3725 UA_UInt32 requestId, UA_UInt32 requestHandle,
3726 size_t opIndex, const void *requestOperation,
3727 void *responseOperation, UA_AsyncResponse **ar);
3728
3729/* Creates an AsyncResponse in-situ when an async operation is encountered. If
3730 * that is the case, the sync responses are moved to the AsyncResponse. */
3731UA_StatusCode
3732UA_Server_processServiceOperationsAsync(UA_Server *server, UA_Session *session,
3733 UA_UInt32 requestId, UA_UInt32 requestHandle,
3734 UA_AsyncServiceOperation operationCallback,
3735 const size_t *requestOperations,
3736 const UA_DataType *requestOperationsType,
3737 size_t *responseOperations,
3738 const UA_DataType *responseOperationsType,
3739 UA_AsyncResponse **ar)
3740UA_FUNC_ATTR_WARN_UNUSED_RESULT;
3741
3742#endif /* UA_MULTITHREADING >= 100 */
3743
3744_UA_END_DECLS
3745
3746
3747/**** amalgamated original file "/src/server/ua_server_internal.h" ****/
3748
3749/* This Source Code Form is subject to the terms of the Mozilla Public
3750 * License, v. 2.0. If a copy of the MPL was not distributed with this
3751 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
3752 *
3753 * Copyright 2019 (c) Fraunhofer IOSB (Author: Klaus Schick)
3754 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
3755 * Copyright 2014, 2017 (c) Florian Palm
3756 * Copyright 2015-2016 (c) Sten Grüner
3757 * Copyright 2015 (c) Chris Iatrou
3758 * Copyright 2015-2016 (c) Oleksiy Vasylyev
3759 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
3760 * Copyright 2017 (c) Julian Grothoff
3761 * Copyright 2019 (c) Kalycito Infotech Private Limited
3762 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
3763 */
3764
3765
3766
3767
3768_UA_BEGIN_DECLS
3769
3770#if UA_MULTITHREADING >= 100
3771#undef UA_THREADSAFE
3772#define UA_THREADSAFE UA_DEPRECATED
3773#endif
3774
3775#ifdef UA_ENABLE_PUBSUB
3776#endif
3777
3778#ifdef UA_ENABLE_DISCOVERY
3779#endif
3780
3781#ifdef UA_ENABLE_SUBSCRIPTIONS
3782
3783typedef struct {
3784 UA_MonitoredItem monitoredItem;
3785 void *context;
3786 union {
3787 UA_Server_DataChangeNotificationCallback dataChangeCallback;
3788 /* UA_Server_EventNotificationCallback eventCallback; */
3789 } callback;
3790} UA_LocalMonitoredItem;
3791
3792#endif
3793
3794typedef enum {
3795 UA_DIAGNOSTICEVENT_CLOSE,
3796 UA_DIAGNOSTICEVENT_REJECT,
3797 UA_DIAGNOSTICEVENT_SECURITYREJECT,
3798 UA_DIAGNOSTICEVENT_TIMEOUT,
3799 UA_DIAGNOSTICEVENT_ABORT,
3800 UA_DIAGNOSTICEVENT_PURGE
3801} UA_DiagnosticEvent;
3802
3803typedef struct channel_entry {
3804 UA_TimerEntry cleanupCallback;
3805 TAILQ_ENTRY(channel_entry) pointers;
3806 UA_SecureChannel channel;
3807} channel_entry;
3808
3809typedef struct session_list_entry {
3810 UA_TimerEntry cleanupCallback;
3811 LIST_ENTRY(session_list_entry) pointers;
3812 UA_Session session;
3813} session_list_entry;
3814
3815typedef enum {
3816 UA_SERVERLIFECYCLE_FRESH,
3817 UA_SERVERLIFECYLE_RUNNING
3818} UA_ServerLifecycle;
3819
3820struct UA_Server {
3821 /* Config */
3822 UA_ServerConfig config;
3823 UA_DateTime startTime;
3824 UA_DateTime endTime; /* Zeroed out. If a time is set, then the server shuts
3825 * down once the time has been reached */
3826
3827 UA_ServerLifecycle state;
3828
3829 /* SecureChannels */
3830 TAILQ_HEAD(, channel_entry) channels;
3831 UA_UInt32 lastChannelId;
3832 UA_UInt32 lastTokenId;
3833
3834#if UA_MULTITHREADING >= 100
3835 UA_AsyncManager asyncManager;
3836#endif
3837
3838 /* Session Management */
3839 LIST_HEAD(session_list, session_list_entry) sessions;
3840 UA_UInt32 sessionCount;
3841 UA_UInt32 activeSessionCount;
3842 UA_Session adminSession; /* Local access to the services (for startup and
3843 * maintenance) uses this Session with all possible
3844 * access rights (Session Id: 1) */
3845
3846 /* Namespaces */
3847 size_t namespacesSize;
3848 UA_String *namespaces;
3849
3850 /* Callbacks with a repetition interval */
3851 UA_Timer timer;
3852
3853 /* For bootstrapping, omit some consistency checks, creating a reference to
3854 * the parent and member instantiation */
3855 UA_Boolean bootstrapNS0;
3856
3857 /* Discovery */
3858#ifdef UA_ENABLE_DISCOVERY
3859 UA_DiscoveryManager discoveryManager;
3860#endif
3861
3862 /* Subscriptions */
3863#ifdef UA_ENABLE_SUBSCRIPTIONS
3864 size_t subscriptionsSize; /* Number of active subscriptions */
3865 size_t monitoredItemsSize; /* Number of active monitored items */
3866 LIST_HEAD(, UA_Subscription) subscriptions; /* All subscriptions in the
3867 * server. They may be detached
3868 * from a session. */
3869 UA_UInt32 lastSubscriptionId; /* To generate unique SubscriptionIds */
3870
3871 /* To be cast to UA_LocalMonitoredItem to get the callback and context */
3872 LIST_HEAD(, UA_MonitoredItem) localMonitoredItems;
3873 UA_UInt32 lastLocalMonitoredItemId;
3874
3875# ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
3876 LIST_HEAD(, UA_ConditionSource) conditionSources;
3877# endif
3878
3879#endif
3880
3881 /* Publish/Subscribe */
3882#ifdef UA_ENABLE_PUBSUB
3883 UA_PubSubManager pubSubManager;
3884#endif
3885
3886#if UA_MULTITHREADING >= 100
3887 UA_Lock networkMutex;
3888 UA_Lock serviceMutex;
3889#endif
3890
3891 /* Statistics */
3892 UA_NetworkStatistics networkStatistics;
3893 UA_SecureChannelStatistics secureChannelStatistics;
3894 UA_ServerDiagnosticsSummaryDataType serverDiagnosticsSummary;
3895};
3896
3897/***********************/
3898/* References Handling */
3899/***********************/
3900
3901extern const struct aa_head refNameTree;
3902
3903const UA_ReferenceTarget *
3904UA_NodeReferenceKind_findTarget(const UA_NodeReferenceKind *rk,
3905 const UA_ExpandedNodeId *targetId);
3906
3907/**************************/
3908/* SecureChannel Handling */
3909/**************************/
3910
3911/* Remove all securechannels */
3912void
3913UA_Server_deleteSecureChannels(UA_Server *server);
3914
3915/* Remove timed out securechannels with a delayed callback. So all currently
3916 * scheduled jobs with a pointer to a securechannel can finish first. */
3917void
3918UA_Server_cleanupTimedOutSecureChannels(UA_Server *server, UA_DateTime nowMonotonic);
3919
3920UA_StatusCode
3921UA_Server_createSecureChannel(UA_Server *server, UA_Connection *connection);
3922
3923UA_StatusCode
3924UA_Server_configSecureChannel(void *application, UA_SecureChannel *channel,
3925 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader);
3926
3927UA_StatusCode
3928sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId,
3929 UA_UInt32 requestHandle, UA_StatusCode statusCode);
3930
3931void
3932UA_Server_closeSecureChannel(UA_Server *server, UA_SecureChannel *channel,
3933 UA_DiagnosticEvent event);
3934
3935/* Gets the a pointer to the context of a security policy supported by the
3936 * server matched by the security policy uri. */
3937UA_SecurityPolicy *
3938getSecurityPolicyByUri(const UA_Server *server,
3939 const UA_ByteString *securityPolicyUri);
3940
3941
3942/********************/
3943/* Session Handling */
3944/********************/
3945
3946UA_StatusCode
3947getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
3948 size_t *foundIndex);
3949
3950UA_StatusCode
3951getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
3952 UA_String *foundUri);
3953
3954UA_StatusCode
3955getBoundSession(UA_Server *server, const UA_SecureChannel *channel,
3956 const UA_NodeId *token, UA_Session **session);
3957
3958UA_StatusCode
3959UA_Server_createSession(UA_Server *server, UA_SecureChannel *channel,
3960 const UA_CreateSessionRequest *request, UA_Session **session);
3961
3962void
3963UA_Server_removeSession(UA_Server *server, session_list_entry *sentry,
3964 UA_DiagnosticEvent event);
3965
3966UA_StatusCode
3967UA_Server_removeSessionByToken(UA_Server *server, const UA_NodeId *token,
3968 UA_DiagnosticEvent event);
3969
3970void
3971UA_Server_cleanupSessions(UA_Server *server, UA_DateTime nowMonotonic);
3972
3973UA_Session *
3974getSessionByToken(UA_Server *server, const UA_NodeId *token);
3975
3976UA_Session *
3977UA_Server_getSessionById(UA_Server *server, const UA_NodeId *sessionId);
3978
3979/*****************/
3980/* Node Handling */
3981/*****************/
3982
3983/* Calls the callback with the node retrieved from the nodestore on top of the
3984 * stack. Either a copy or the original node for in-situ editing. Depends on
3985 * multithreading and the nodestore.*/
3986typedef UA_StatusCode (*UA_EditNodeCallback)(UA_Server*, UA_Session*,
3987 UA_Node *node, void*);
3988UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session,
3989 const UA_NodeId *nodeId,
3990 UA_EditNodeCallback callback,
3991 void *data);
3992
3993/*********************/
3994/* Utility Functions */
3995/*********************/
3996
3997void setupNs1Uri(UA_Server *server);
3998UA_UInt16 addNamespace(UA_Server *server, const UA_String name);
3999
4000UA_Boolean
4001UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head);
4002
4003/* Recursively searches "upwards" in the tree following specific reference types */
4004UA_Boolean
4005isNodeInTree(UA_Server *server, const UA_NodeId *leafNode,
4006 const UA_NodeId *nodeToFind, const UA_ReferenceTypeSet *relevantRefs);
4007
4008/* Convenience function with just a single ReferenceTypeIndex */
4009UA_Boolean
4010isNodeInTree_singleRef(UA_Server *server, const UA_NodeId *leafNode,
4011 const UA_NodeId *nodeToFind, const UA_Byte relevantRefTypeIndex);
4012
4013/* Returns an array with the hierarchy of nodes. The start nodes can be returned
4014 * as well. The returned array starts at the leaf and continues "upwards" or
4015 * "downwards". Duplicate entries are removed. */
4016UA_StatusCode
4017browseRecursive(UA_Server *server, size_t startNodesSize, const UA_NodeId *startNodes,
4018 UA_BrowseDirection browseDirection, const UA_ReferenceTypeSet *refTypes,
4019 UA_UInt32 nodeClassMask, UA_Boolean includeStartNodes,
4020 size_t *resultsSize, UA_ExpandedNodeId **results);
4021
4022/* Get the bitfield indices of a ReferenceType and possibly its subtypes.
4023 * refType must point to a ReferenceTypeNode. */
4024UA_StatusCode
4025referenceTypeIndices(UA_Server *server, const UA_NodeId *refType,
4026 UA_ReferenceTypeSet *indices, UA_Boolean includeSubtypes);
4027
4028/* Returns the recursive type and interface hierarchy of the node */
4029UA_StatusCode
4030getParentTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *typeNode,
4031 UA_NodeId **typeHierarchy, size_t *typeHierarchySize);
4032
4033/* Returns the recursive interface hierarchy of the node */
4034UA_StatusCode
4035getAllInterfaceChildNodeIds(UA_Server *server, const UA_NodeId *objectNode, const UA_NodeId *objectTypeNode,
4036 UA_NodeId **interfaceChildNodes, size_t *interfaceChildNodesSize);
4037
4038#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
4039
4040UA_StatusCode
4041UA_getConditionId(UA_Server *server, const UA_NodeId *conditionNodeId,
4042 UA_NodeId *outConditionId);
4043
4044void
4045UA_ConditionList_delete(UA_Server *server);
4046
4047UA_Boolean
4048isConditionOrBranch(UA_Server *server,
4049 const UA_NodeId *condition,
4050 const UA_NodeId *conditionSource,
4051 UA_Boolean *isCallerAC);
4052
4053#endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
4054
4055/* Returns the type node from the node on the stack top. The type node is pushed
4056 * on the stack and returned. */
4057const UA_Node *
4058getNodeType(UA_Server *server, const UA_NodeHead *nodeHead);
4059
4060UA_StatusCode
4061sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
4062 UA_UInt32 requestId, UA_Response *response, const UA_DataType *responseType);
4063
4064/* Many services come as an array of operations. This function generalizes the
4065 * processing of the operations. */
4066typedef void (*UA_ServiceOperation)(UA_Server *server, UA_Session *session,
4067 const void *context,
4068 const void *requestOperation,
4069 void *responseOperation);
4070
4071UA_StatusCode
4072UA_Server_processServiceOperations(UA_Server *server, UA_Session *session,
4073 UA_ServiceOperation operationCallback,
4074 const void *context,
4075 const size_t *requestOperations,
4076 const UA_DataType *requestOperationsType,
4077 size_t *responseOperations,
4078 const UA_DataType *responseOperationsType)
4079 UA_FUNC_ATTR_WARN_UNUSED_RESULT;
4080
4081/******************************************/
4082/* Internal function calls, without locks */
4083/******************************************/
4084UA_StatusCode
4085deleteNode(UA_Server *server, const UA_NodeId nodeId,
4086 UA_Boolean deleteReferences);
4087
4088UA_StatusCode
4089addNode(UA_Server *server, const UA_NodeClass nodeClass, const UA_NodeId *requestedNewNodeId,
4090 const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
4091 const UA_QualifiedName browseName, const UA_NodeId *typeDefinition,
4092 const UA_NodeAttributes *attr, const UA_DataType *attributeType,
4093 void *nodeContext, UA_NodeId *outNewNodeId);
4094
4095UA_StatusCode
4096addRef(UA_Server *server, UA_Session *session, const UA_NodeId *sourceId,
4097 const UA_NodeId *referenceTypeId, const UA_NodeId *targetId,
4098 UA_Boolean forward);
4099
4100UA_StatusCode
4101setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
4102 const UA_DataSource dataSource);
4103
4104UA_StatusCode
4105writeAttribute(UA_Server *server, UA_Session *session,
4106 const UA_NodeId *nodeId, const UA_AttributeId attributeId,
4107 const void *attr, const UA_DataType *attr_type);
4108
4109static UA_INLINE UA_StatusCode
4110writeValueAttribute(UA_Server *server, UA_Session *session,
4111 const UA_NodeId *nodeId, const UA_Variant *value) {
4112 return writeAttribute(server, session, nodeId, attributeId: UA_ATTRIBUTEID_VALUE,
4113 attr: value, attr_type: &UA_TYPES[UA_TYPES_VARIANT]);
4114}
4115
4116UA_DataValue
4117readAttribute(UA_Server *server, const UA_ReadValueId *item,
4118 UA_TimestampsToReturn timestamps);
4119
4120UA_StatusCode
4121readWithReadValue(UA_Server *server, const UA_NodeId *nodeId,
4122 const UA_AttributeId attributeId, void *v);
4123
4124UA_StatusCode
4125readObjectProperty(UA_Server *server, const UA_NodeId objectId,
4126 const UA_QualifiedName propertyName,
4127 UA_Variant *value);
4128
4129UA_BrowsePathResult
4130translateBrowsePathToNodeIds(UA_Server *server, const UA_BrowsePath *browsePath);
4131
4132#ifdef UA_ENABLE_SUBSCRIPTIONS
4133
4134void monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem);
4135
4136UA_Subscription *
4137UA_Server_getSubscriptionById(UA_Server *server, UA_UInt32 subscriptionId);
4138
4139#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
4140UA_StatusCode
4141triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
4142 const UA_NodeId origin, UA_ByteString *outEventId,
4143 const UA_Boolean deleteEventNode);
4144
4145/* Filters the given event with the given filter and writes the results into a
4146 * notification */
4147UA_StatusCode
4148filterEvent(UA_Server *server, UA_Session *session,
4149 const UA_NodeId *eventNode, UA_EventFilter *filter,
4150 UA_EventFieldList *efl, UA_EventFilterResult *result);
4151
4152#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
4153#endif /* UA_ENABLE_SUBSCRIPTIONS */
4154
4155UA_BrowsePathResult
4156browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
4157 size_t browsePathSize, const UA_QualifiedName *browsePath);
4158
4159UA_StatusCode
4160writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
4161 const UA_QualifiedName propertyName, const UA_Variant value);
4162
4163UA_StatusCode
4164getNodeContext(UA_Server *server, UA_NodeId nodeId, void **nodeContext);
4165
4166UA_StatusCode
4167setNodeContext(UA_Server *server, UA_NodeId nodeId, void *nodeContext);
4168
4169void
4170removeCallback(UA_Server *server, UA_UInt64 callbackId);
4171
4172UA_StatusCode
4173changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId, UA_Double interval_ms);
4174
4175UA_StatusCode
4176addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
4177 void *data, UA_Double interval_ms, UA_UInt64 *callbackId);
4178
4179#ifdef UA_ENABLE_DISCOVERY
4180UA_StatusCode
4181register_server_with_discovery_server(UA_Server *server,
4182 void *client,
4183 const UA_Boolean isUnregister,
4184 const char* semaphoreFilePath);
4185#endif
4186
4187/***********/
4188/* RefTree */
4189/***********/
4190
4191/* A RefTree is a sorted set of NodeIds that ensures we consider each node just
4192 * once. It holds a single array for both the ExpandedNodeIds and the entries of
4193 * a tree-structure for fast lookup. A single realloc operation (with some
4194 * pointer repairing) can be used to increase the capacity of the RefTree.
4195 *
4196 * When the RefTree is complete, the tree-part at the end of the targets array
4197 * can be ignored / cut away to use it as a simple ExpandedNodeId array.
4198 *
4199 * The layout of the targets array is as follows:
4200 *
4201 * | Targets [ExpandedNodeId, n times] | Tree [RefEntry, n times] | */
4202
4203#define UA_REFTREE_INITIAL_SIZE 16
4204
4205typedef struct RefEntry {
4206 ZIP_ENTRY(RefEntry) zipfields;
4207 const UA_ExpandedNodeId *target;
4208 UA_UInt32 targetHash; /* Hash of the target nodeid */
4209} RefEntry;
4210
4211ZIP_HEAD(RefHead, RefEntry);
4212typedef struct RefHead RefHead;
4213
4214typedef struct {
4215 UA_ExpandedNodeId *targets;
4216 RefHead head;
4217 size_t capacity; /* available space */
4218 size_t size; /* used space */
4219} RefTree;
4220
4221UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
4222RefTree_init(RefTree *rt);
4223
4224void RefTree_clear(RefTree *rt);
4225
4226UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
4227RefTree_addNodeId(RefTree *rt, const UA_NodeId *target, UA_Boolean *duplicate);
4228
4229UA_Boolean
4230RefTree_contains(RefTree *rt, const UA_ExpandedNodeId *target);
4231
4232UA_Boolean
4233RefTree_containsNodeId(RefTree *rt, const UA_NodeId *target);
4234
4235/***************************************/
4236/* Check Information Model Consistency */
4237/***************************************/
4238
4239/* Read a node attribute in the context of a "checked-out" node. So the
4240 * attribute will not be copied when possible. The variant then points into the
4241 * node and has UA_VARIANT_DATA_NODELETE set. */
4242void
4243ReadWithNode(const UA_Node *node, UA_Server *server, UA_Session *session,
4244 UA_TimestampsToReturn timestampsToReturn,
4245 const UA_ReadValueId *id, UA_DataValue *v);
4246
4247UA_StatusCode
4248readValueAttribute(UA_Server *server, UA_Session *session,
4249 const UA_VariableNode *vn, UA_DataValue *v);
4250
4251/* Test whether the value matches a variable definition given by
4252 * - datatype
4253 * - valueranke
4254 * - array dimensions.
4255 * Sometimes it can be necessary to transform the content of the value, e.g.
4256 * byte array to bytestring or uint32 to some enum. If editableValue is non-NULL,
4257 * we try to create a matching variant that points to the original data.
4258 *
4259 * The reason is set whenever the return value is false */
4260UA_Boolean
4261compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetDataTypeId,
4262 UA_Int32 targetValueRank, size_t targetArrayDimensionsSize,
4263 const UA_UInt32 *targetArrayDimensions, const UA_Variant *value,
4264 const UA_NumericRange *range, const char **reason);
4265
4266/* Is the DataType compatible */
4267UA_Boolean
4268compatibleDataTypes(UA_Server *server, const UA_NodeId *dataType,
4269 const UA_NodeId *constraintDataType);
4270
4271/* Set to the target type if compatible */
4272void
4273adjustValueType(UA_Server *server, UA_Variant *value,
4274 const UA_NodeId *targetDataTypeId);
4275
4276/* Is the Value compatible with the DataType? Can perform additional checks
4277 * compared to compatibleDataTypes. */
4278UA_Boolean
4279compatibleValueDataType(UA_Server *server, const UA_DataType *dataType,
4280 const UA_NodeId *constraintDataType);
4281
4282
4283UA_Boolean
4284compatibleArrayDimensions(size_t constraintArrayDimensionsSize,
4285 const UA_UInt32 *constraintArrayDimensions,
4286 size_t testArrayDimensionsSize,
4287 const UA_UInt32 *testArrayDimensions);
4288
4289UA_Boolean
4290compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimensionsSize,
4291 const UA_UInt32 *targetArrayDimensions);
4292
4293UA_Boolean
4294compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session,
4295 UA_Int32 valueRank, size_t arrayDimensionsSize);
4296
4297UA_Boolean
4298compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank);
4299
4300struct BrowseOpts {
4301 UA_UInt32 maxReferences;
4302 UA_Boolean recursive;
4303};
4304
4305void
4306Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxrefs,
4307 const UA_BrowseDescription *descr, UA_BrowseResult *result);
4308
4309UA_DataValue
4310UA_Server_readWithSession(UA_Server *server, UA_Session *session,
4311 const UA_ReadValueId *item,
4312 UA_TimestampsToReturn timestampsToReturn);
4313
4314/*****************************/
4315/* AddNodes Begin and Finish */
4316/*****************************/
4317
4318/* Creates a new node in the nodestore. */
4319UA_StatusCode
4320AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
4321 const UA_AddNodesItem *item, UA_NodeId *outNewNodeId);
4322
4323/* Check the reference to the parent node; Add references. */
4324UA_StatusCode
4325AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
4326 const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
4327 const UA_NodeId *typeDefinitionId);
4328
4329/* Type-check type-definition; Run the constructors */
4330UA_StatusCode
4331AddNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId);
4332
4333/**********************/
4334/* Create Namespace 0 */
4335/**********************/
4336
4337UA_StatusCode UA_Server_initNS0(UA_Server *server);
4338
4339UA_StatusCode writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
4340 size_t length, const UA_DataType *type);
4341
4342#ifdef UA_ENABLE_DIAGNOSTICS
4343void createSessionObject(UA_Server *server, UA_Session *session);
4344
4345void createSubscriptionObject(UA_Server *server, UA_Session *session,
4346 UA_Subscription *sub);
4347
4348UA_StatusCode
4349readDiagnostics(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
4350 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp,
4351 const UA_NumericRange *range, UA_DataValue *value);
4352
4353UA_StatusCode
4354readSubscriptionDiagnosticsArray(UA_Server *server,
4355 const UA_NodeId *sessionId, void *sessionContext,
4356 const UA_NodeId *nodeId, void *nodeContext,
4357 UA_Boolean sourceTimestamp,
4358 const UA_NumericRange *range, UA_DataValue *value);
4359
4360UA_StatusCode
4361readSessionDiagnosticsArray(UA_Server *server,
4362 const UA_NodeId *sessionId, void *sessionContext,
4363 const UA_NodeId *nodeId, void *nodeContext,
4364 UA_Boolean sourceTimestamp,
4365 const UA_NumericRange *range, UA_DataValue *value);
4366
4367UA_StatusCode
4368readSessionSecurityDiagnostics(UA_Server *server,
4369 const UA_NodeId *sessionId, void *sessionContext,
4370 const UA_NodeId *nodeId, void *nodeContext,
4371 UA_Boolean sourceTimestamp,
4372 const UA_NumericRange *range, UA_DataValue *value);
4373#endif
4374
4375/***************************/
4376/* Nodestore Access Macros */
4377/***************************/
4378
4379#define UA_NODESTORE_NEW(server, nodeClass) \
4380 server->config.nodestore.newNode(server->config.nodestore.context, nodeClass)
4381
4382#define UA_NODESTORE_DELETE(server, node) \
4383 server->config.nodestore.deleteNode(server->config.nodestore.context, node)
4384
4385#define UA_NODESTORE_GET(server, nodeid) \
4386 server->config.nodestore.getNode(server->config.nodestore.context, nodeid)
4387
4388/* Returns NULL if the target is an external Reference (per the ExpandedNodeId) */
4389const UA_Node *
4390UA_NODESTORE_GETFROMREF(UA_Server *server, UA_NodePointer target);
4391
4392#define UA_NODESTORE_RELEASE(server, node) \
4393 server->config.nodestore.releaseNode(server->config.nodestore.context, node)
4394
4395#define UA_NODESTORE_GETCOPY(server, nodeid, outnode) \
4396 server->config.nodestore.getNodeCopy(server->config.nodestore.context, \
4397 nodeid, outnode)
4398
4399#define UA_NODESTORE_INSERT(server, node, addedNodeId) \
4400 server->config.nodestore.insertNode(server->config.nodestore.context, \
4401 node, addedNodeId)
4402
4403#define UA_NODESTORE_REPLACE(server, node) \
4404 server->config.nodestore.replaceNode(server->config.nodestore.context, node)
4405
4406#define UA_NODESTORE_REMOVE(server, nodeId) \
4407 server->config.nodestore.removeNode(server->config.nodestore.context, nodeId)
4408
4409#define UA_NODESTORE_GETREFERENCETYPEID(server, index) \
4410 server->config.nodestore.getReferenceTypeId(server->config.nodestore.context, \
4411 index)
4412
4413_UA_END_DECLS
4414
4415
4416/**** amalgamated original file "/src/server/ua_services.h" ****/
4417
4418/* This Source Code Form is subject to the terms of the Mozilla Public
4419 * License, v. 2.0. If a copy of the MPL was not distributed with this
4420 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4421 *
4422 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
4423 * Copyright 2014-2017 (c) Florian Palm
4424 * Copyright 2015 (c) Sten Grüner
4425 * Copyright 2014 (c) LEvertz
4426 * Copyright 2015 (c) Chris Iatrou
4427 * Copyright 2015 (c) Christian Fimmers
4428 * Copyright 2015-2016 (c) Oleksiy Vasylyev
4429 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
4430 */
4431
4432
4433
4434
4435_UA_BEGIN_DECLS
4436
4437/**
4438 * .. _services:
4439 *
4440 * Services
4441 * ========
4442 *
4443 * In OPC UA, all communication is based on service calls, each consisting of a
4444 * request and a response message. These messages are defined as data structures
4445 * with a binary encoding and listed in :ref:`generated-types`. Since all
4446 * Services are pre-defined in the standard, they cannot be modified by the
4447 * user. But you can use the :ref:`Call <method-services>` service to invoke
4448 * user-defined methods on the server.
4449 *
4450 * The following service signatures are internal and *not visible to users*.
4451 * Still, we present them here for an overview of the capabilities of OPC UA.
4452 * Please refer to the :ref:`client` and :ref:`server` API where the services
4453 * are exposed to end users. Please see part 4 of the OPC UA standard for the
4454 * authoritative definition of the service and their behaviour.
4455 *
4456 * Most services take as input the server, the current session and pointers to
4457 * the request and response structures. Possible error codes are returned as
4458 * part of the response. */
4459
4460typedef void (*UA_Service)(UA_Server*, UA_Session*,
4461 const void *request, void *response);
4462
4463typedef void (*UA_ChannelService)(UA_Server*, UA_SecureChannel*,
4464 const void *request, void *response);
4465
4466/**
4467 * Discovery Service Set
4468 * ---------------------
4469 * This Service Set defines Services used to discover the Endpoints implemented
4470 * by a Server and to read the security configuration for those Endpoints.
4471 *
4472 * FindServers Service
4473 * ^^^^^^^^^^^^^^^^^^^
4474 * Returns the Servers known to a Server or Discovery Server. The Client may
4475 * reduce the number of results returned by specifying filter criteria */
4476void Service_FindServers(UA_Server *server, UA_Session *session,
4477 const UA_FindServersRequest *request,
4478 UA_FindServersResponse *response);
4479
4480/**
4481 * GetEndpoints Service
4482 * ^^^^^^^^^^^^^^^^^^^^
4483 * Returns the Endpoints supported by a Server and all of the configuration
4484 * information required to establish a SecureChannel and a Session. */
4485void Service_GetEndpoints(UA_Server *server, UA_Session *session,
4486 const UA_GetEndpointsRequest *request,
4487 UA_GetEndpointsResponse *response);
4488
4489#ifdef UA_ENABLE_DISCOVERY
4490
4491# ifdef UA_ENABLE_DISCOVERY_MULTICAST
4492
4493/**
4494 * FindServersOnNetwork Service
4495 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4496 * Returns the Servers known to a Discovery Server. Unlike FindServer,
4497 * this Service is only implemented by Discovery Servers. It additionally
4498 * returns servers which may have been detected through Multicast. */
4499void Service_FindServersOnNetwork(UA_Server *server, UA_Session *session,
4500 const UA_FindServersOnNetworkRequest *request,
4501 UA_FindServersOnNetworkResponse *response);
4502
4503# endif /* UA_ENABLE_DISCOVERY_MULTICAST */
4504
4505/**
4506 * RegisterServer
4507 * ^^^^^^^^^^^^^^
4508 * Registers a remote server in the local discovery service. */
4509void Service_RegisterServer(UA_Server *server, UA_Session *session,
4510 const UA_RegisterServerRequest *request,
4511 UA_RegisterServerResponse *response);
4512
4513/**
4514 * RegisterServer2
4515 * ^^^^^^^^^^^^^^^
4516 * This Service allows a Server to register its DiscoveryUrls and capabilities
4517 * with a Discovery Server. It extends the registration information from
4518 * RegisterServer with information necessary for FindServersOnNetwork. */
4519void Service_RegisterServer2(UA_Server *server, UA_Session *session,
4520 const UA_RegisterServer2Request *request,
4521 UA_RegisterServer2Response *response);
4522
4523#endif /* UA_ENABLE_DISCOVERY */
4524
4525/**
4526 * SecureChannel Service Set
4527 * -------------------------
4528 * This Service Set defines Services used to open a communication channel that
4529 * ensures the confidentiality and Integrity of all Messages exchanged with the
4530 * Server.
4531 *
4532 * OpenSecureChannel Service
4533 * ^^^^^^^^^^^^^^^^^^^^^^^^^
4534 * Open or renew a SecureChannel that can be used to ensure Confidentiality and
4535 * Integrity for Message exchange during a Session. */
4536void Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel* channel,
4537 const UA_OpenSecureChannelRequest *request,
4538 UA_OpenSecureChannelResponse *response);
4539
4540/**
4541 * CloseSecureChannel Service
4542 * ^^^^^^^^^^^^^^^^^^^^^^^^^^
4543 * Used to terminate a SecureChannel. */
4544void Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel);
4545
4546/**
4547 * Session Service Set
4548 * -------------------
4549 * This Service Set defines Services for an application layer connection
4550 * establishment in the context of a Session.
4551 *
4552 * CreateSession Service
4553 * ^^^^^^^^^^^^^^^^^^^^^
4554 * Used by an OPC UA Client to create a Session and the Server returns two
4555 * values which uniquely identify the Session. The first value is the sessionId
4556 * which is used to identify the Session in the audit logs and in the Server's
4557 * address space. The second is the authenticationToken which is used to
4558 * associate an incoming request with a Session. */
4559void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
4560 const UA_CreateSessionRequest *request,
4561 UA_CreateSessionResponse *response);
4562
4563/**
4564 * ActivateSession
4565 * ^^^^^^^^^^^^^^^
4566 * Used by the Client to submit its SoftwareCertificates to the Server for
4567 * validation and to specify the identity of the user associated with the
4568 * Session. This Service request shall be issued by the Client before it issues
4569 * any other Service request after CreateSession. Failure to do so shall cause
4570 * the Server to close the Session. */
4571void Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
4572 const UA_ActivateSessionRequest *request,
4573 UA_ActivateSessionResponse *response);
4574
4575/**
4576 * CloseSession
4577 * ^^^^^^^^^^^^
4578 * Used to terminate a Session. */
4579void Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
4580 const UA_CloseSessionRequest *request,
4581 UA_CloseSessionResponse *response);
4582
4583/**
4584 * Cancel Service
4585 * ^^^^^^^^^^^^^^
4586 * Used to cancel outstanding Service requests. Successfully cancelled service
4587 * requests shall respond with Bad_RequestCancelledByClient. */
4588/* Not Implemented */
4589
4590/**
4591 * NodeManagement Service Set
4592 * --------------------------
4593 * This Service Set defines Services to add and delete AddressSpace Nodes and
4594 * References between them. All added Nodes continue to exist in the
4595 * AddressSpace even if the Client that created them disconnects from the
4596 * Server.
4597 *
4598 * AddNodes Service
4599 * ^^^^^^^^^^^^^^^^
4600 * Used to add one or more Nodes into the AddressSpace hierarchy.
4601 * If the type or one of the supertypes has any HasInterface references
4602 * (see OPC 10001-7 - Amendment 7, 4.9.2), the child nodes of the interfaces
4603 * are added to the new object.
4604*/
4605void Service_AddNodes(UA_Server *server, UA_Session *session,
4606 const UA_AddNodesRequest *request,
4607 UA_AddNodesResponse *response);
4608
4609/**
4610 * AddReferences Service
4611 * ^^^^^^^^^^^^^^^^^^^^^
4612 * Used to add one or more References to one or more Nodes.*/
4613void Service_AddReferences(UA_Server *server, UA_Session *session,
4614 const UA_AddReferencesRequest *request,
4615 UA_AddReferencesResponse *response);
4616
4617/**
4618 * DeleteNodes Service
4619 * ^^^^^^^^^^^^^^^^^^^
4620 * Used to delete one or more Nodes from the AddressSpace. */
4621void Service_DeleteNodes(UA_Server *server, UA_Session *session,
4622 const UA_DeleteNodesRequest *request,
4623 UA_DeleteNodesResponse *response);
4624
4625/**
4626 * DeleteReferences
4627 * ^^^^^^^^^^^^^^^^
4628 * Used to delete one or more References of a Node. */
4629void Service_DeleteReferences(UA_Server *server, UA_Session *session,
4630 const UA_DeleteReferencesRequest *request,
4631 UA_DeleteReferencesResponse *response);
4632
4633/**
4634 * .. _view-services:
4635 *
4636 * View Service Set
4637 * ----------------
4638 * Clients use the browse Services of the View Service Set to navigate through
4639 * the AddressSpace or through a View which is a subset of the AddressSpace.
4640 *
4641 * Browse Service
4642 * ^^^^^^^^^^^^^^
4643 * Used to discover the References of a specified Node. The browse can be
4644 * further limited by the use of a View. This Browse Service also supports a
4645 * primitive filtering capability. */
4646void Service_Browse(UA_Server *server, UA_Session *session,
4647 const UA_BrowseRequest *request,
4648 UA_BrowseResponse *response);
4649
4650/**
4651 * BrowseNext Service
4652 * ^^^^^^^^^^^^^^^^^^
4653 * Used to request the next set of Browse or BrowseNext response information
4654 * that is too large to be sent in a single response. "Too large" in this
4655 * context means that the Server is not able to return a larger response or that
4656 * the number of results to return exceeds the maximum number of results to
4657 * return that was specified by the Client in the original Browse request. */
4658void Service_BrowseNext(UA_Server *server, UA_Session *session,
4659 const UA_BrowseNextRequest *request,
4660 UA_BrowseNextResponse *response);
4661
4662/**
4663 * TranslateBrowsePathsToNodeIds Service
4664 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4665 * Used to translate textual node paths to their respective ids. */
4666void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
4667 const UA_TranslateBrowsePathsToNodeIdsRequest *request,
4668 UA_TranslateBrowsePathsToNodeIdsResponse *response);
4669
4670/**
4671 * RegisterNodes Service
4672 * ^^^^^^^^^^^^^^^^^^^^^
4673 * Used by Clients to register the Nodes that they know they will access
4674 * repeatedly (e.g. Write, Call). It allows Servers to set up anything needed so
4675 * that the access operations will be more efficient. */
4676void Service_RegisterNodes(UA_Server *server, UA_Session *session,
4677 const UA_RegisterNodesRequest *request,
4678 UA_RegisterNodesResponse *response);
4679
4680/**
4681 * UnregisterNodes Service
4682 * ^^^^^^^^^^^^^^^^^^^^^^^
4683 * This Service is used to unregister NodeIds that have been obtained via the
4684 * RegisterNodes service. */
4685void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
4686 const UA_UnregisterNodesRequest *request,
4687 UA_UnregisterNodesResponse *response);
4688
4689/**
4690 * Query Service Set
4691 * -----------------
4692 * This Service Set is used to issue a Query to a Server. OPC UA Query is
4693 * generic in that it provides an underlying storage mechanism independent Query
4694 * capability that can be used to access a wide variety of OPC UA data stores
4695 * and information management systems. OPC UA Query permits a Client to access
4696 * data maintained by a Server without any knowledge of the logical schema used
4697 * for internal storage of the data. Knowledge of the AddressSpace is
4698 * sufficient.
4699 *
4700 * QueryFirst Service
4701 * ^^^^^^^^^^^^^^^^^^
4702 * This Service is used to issue a Query request to the Server. */
4703/* Not Implemented */
4704
4705/**
4706 * QueryNext Service
4707 * ^^^^^^^^^^^^^^^^^
4708 * This Service is used to request the next set of QueryFirst or QueryNext
4709 * response information that is too large to be sent in a single response. */
4710/* Not Impelemented */
4711
4712/**
4713 * Attribute Service Set
4714 * ---------------------
4715 * This Service Set provides Services to access Attributes that are part of
4716 * Nodes.
4717 *
4718 * Read Service
4719 * ^^^^^^^^^^^^
4720 * Used to read attributes of nodes. For constructed attribute values whose
4721 * elements are indexed, such as an array, this Service allows Clients to read
4722 * the entire set of indexed values as a composite, to read individual elements
4723 * or to read ranges of elements of the composite. */
4724void Service_Read(UA_Server *server, UA_Session *session,
4725 const UA_ReadRequest *request,
4726 UA_ReadResponse *response);
4727
4728/**
4729 * Write Service
4730 * ^^^^^^^^^^^^^
4731 * Used to write attributes of nodes. For constructed attribute values whose
4732 * elements are indexed, such as an array, this Service allows Clients to write
4733 * the entire set of indexed values as a composite, to write individual elements
4734 * or to write ranges of elements of the composite. */
4735void Service_Write(UA_Server *server, UA_Session *session,
4736 const UA_WriteRequest *request,
4737 UA_WriteResponse *response);
4738
4739/**
4740 * HistoryRead Service
4741 * ^^^^^^^^^^^^^^^^^^^
4742 * Used to read historical values or Events of one or more Nodes. Servers may
4743 * make historical values available to Clients using this Service, although the
4744 * historical values themselves are not visible in the AddressSpace. */
4745#ifdef UA_ENABLE_HISTORIZING
4746void Service_HistoryRead(UA_Server *server, UA_Session *session,
4747 const UA_HistoryReadRequest *request,
4748 UA_HistoryReadResponse *response);
4749
4750/**
4751 * HistoryUpdate Service
4752 * ^^^^^^^^^^^^^^^^^^^^^
4753 * Used to update historical values or Events of one or more Nodes. Several
4754 * request parameters indicate how the Server is to update the historical value
4755 * or Event. Valid actions are Insert, Replace or Delete. */
4756void
4757Service_HistoryUpdate(UA_Server *server, UA_Session *session,
4758 const UA_HistoryUpdateRequest *request,
4759 UA_HistoryUpdateResponse *response);
4760#endif
4761
4762/**
4763 * .. _method-services:
4764 *
4765 * Method Service Set
4766 * ------------------
4767 * The Method Service Set defines the means to invoke methods. A method shall be
4768 * a component of an Object. See the section on :ref:`MethodNodes <methodnode>`
4769 * for more information.
4770 *
4771 * Call Service
4772 * ^^^^^^^^^^^^
4773 * Used to call (invoke) a methods. Each method call is invoked within the
4774 * context of an existing Session. If the Session is terminated, the results of
4775 * the method's execution cannot be returned to the Client and are discarded. */
4776#ifdef UA_ENABLE_METHODCALLS
4777void Service_Call(UA_Server *server, UA_Session *session,
4778 const UA_CallRequest *request,
4779 UA_CallResponse *response);
4780
4781# if UA_MULTITHREADING >= 100
4782void Service_CallAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId,
4783 const UA_CallRequest *request, UA_CallResponse *response,
4784 UA_Boolean *finished);
4785#endif
4786#endif
4787
4788#ifdef UA_ENABLE_SUBSCRIPTIONS
4789
4790/**
4791 * MonitoredItem Service Set
4792 * -------------------------
4793 * Clients define MonitoredItems to subscribe to data and Events. Each
4794 * MonitoredItem identifies the item to be monitored and the Subscription to use
4795 * to send Notifications. The item to be monitored may be any Node Attribute.
4796 *
4797 * CreateMonitoredItems Service
4798 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4799 * Used to create and add one or more MonitoredItems to a Subscription. A
4800 * MonitoredItem is deleted automatically by the Server when the Subscription is
4801 * deleted. Deleting a MonitoredItem causes its entire set of triggered item
4802 * links to be deleted, but has no effect on the MonitoredItems referenced by
4803 * the triggered items. */
4804void Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
4805 const UA_CreateMonitoredItemsRequest *request,
4806 UA_CreateMonitoredItemsResponse *response);
4807
4808/**
4809 * DeleteMonitoredItems Service
4810 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4811 * Used to remove one or more MonitoredItems of a Subscription. When a
4812 * MonitoredItem is deleted, its triggered item links are also deleted. */
4813void Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
4814 const UA_DeleteMonitoredItemsRequest *request,
4815 UA_DeleteMonitoredItemsResponse *response);
4816
4817/**
4818 * ModifyMonitoredItems Service
4819 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4820 * Used to modify MonitoredItems of a Subscription. Changes to the MonitoredItem
4821 * settings shall be applied immediately by the Server. They take effect as soon
4822 * as practical but not later than twice the new revisedSamplingInterval.
4823 *
4824 * Illegal request values for parameters that can be revised do not generate
4825 * errors. Instead the server will choose default values and indicate them in
4826 * the corresponding revised parameter. */
4827void Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
4828 const UA_ModifyMonitoredItemsRequest *request,
4829 UA_ModifyMonitoredItemsResponse *response);
4830
4831/**
4832 * SetMonitoringMode Service
4833 * ^^^^^^^^^^^^^^^^^^^^^^^^^
4834 * Used to set the monitoring mode for one or more MonitoredItems of a
4835 * Subscription. */
4836void Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
4837 const UA_SetMonitoringModeRequest *request,
4838 UA_SetMonitoringModeResponse *response);
4839
4840/**
4841 * SetTriggering Service
4842 * ^^^^^^^^^^^^^^^^^^^^^
4843 * Used to create and delete triggering links for a triggering item. */
4844void Service_SetTriggering(UA_Server *server, UA_Session *session,
4845 const UA_SetTriggeringRequest *request,
4846 UA_SetTriggeringResponse *response);
4847
4848/**
4849 * Subscription Service Set
4850 * ------------------------
4851 * Subscriptions are used to report Notifications to the Client.
4852 *
4853 * CreateSubscription Service
4854 * ^^^^^^^^^^^^^^^^^^^^^^^^^^
4855 * Used to create a Subscription. Subscriptions monitor a set of MonitoredItems
4856 * for Notifications and return them to the Client in response to Publish
4857 * requests. */
4858void Service_CreateSubscription(UA_Server *server, UA_Session *session,
4859 const UA_CreateSubscriptionRequest *request,
4860 UA_CreateSubscriptionResponse *response);
4861
4862/**
4863 * ModifySubscription Service
4864 * ^^^^^^^^^^^^^^^^^^^^^^^^^^
4865 * Used to modify a Subscription. */
4866void Service_ModifySubscription(UA_Server *server, UA_Session *session,
4867 const UA_ModifySubscriptionRequest *request,
4868 UA_ModifySubscriptionResponse *response);
4869
4870/**
4871 * SetPublishingMode Service
4872 * ^^^^^^^^^^^^^^^^^^^^^^^^^
4873 * Used to enable sending of Notifications on one or more Subscriptions. */
4874void Service_SetPublishingMode(UA_Server *server, UA_Session *session,
4875 const UA_SetPublishingModeRequest *request,
4876 UA_SetPublishingModeResponse *response);
4877
4878/**
4879 * Publish Service
4880 * ^^^^^^^^^^^^^^^
4881 * Used for two purposes. First, it is used to acknowledge the receipt of
4882 * NotificationMessages for one or more Subscriptions. Second, it is used to
4883 * request the Server to return a NotificationMessage or a keep-alive
4884 * Message.
4885 *
4886 * Note that the service signature is an exception and does not contain a
4887 * pointer to a PublishResponse. That is because the service queues up publish
4888 * requests internally and sends responses asynchronously based on timeouts.
4889 *
4890 * Also, this is the only service method that returns a StatusCode. This
4891 * simplifies keeping track of the diagnostics statistics. */
4892UA_StatusCode
4893Service_Publish(UA_Server *server, UA_Session *session,
4894 const UA_PublishRequest *request, UA_UInt32 requestId);
4895
4896/**
4897 * Republish Service
4898 * ^^^^^^^^^^^^^^^^^
4899 * Requests the Subscription to republish a NotificationMessage from its
4900 * retransmission queue. */
4901void Service_Republish(UA_Server *server, UA_Session *session,
4902 const UA_RepublishRequest *request,
4903 UA_RepublishResponse *response);
4904
4905/**
4906 * DeleteSubscriptions Service
4907 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
4908 * Invoked to delete one or more Subscriptions that belong to the Client's
4909 * Session. */
4910void Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
4911 const UA_DeleteSubscriptionsRequest *request,
4912 UA_DeleteSubscriptionsResponse *response);
4913
4914/**
4915 * TransferSubscription Service
4916 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4917 * Used to transfer a Subscription and its MonitoredItems from one Session to
4918 * another. For example, a Client may need to reopen a Session and then transfer
4919 * its Subscriptions to that Session. It may also be used by one Client to take
4920 * over a Subscription from another Client by transferring the Subscription to
4921 * its Session. */
4922void Service_TransferSubscriptions(UA_Server *server, UA_Session *session,
4923 const UA_TransferSubscriptionsRequest *request,
4924 UA_TransferSubscriptionsResponse *response);
4925
4926#endif /* UA_ENABLE_SUBSCRIPTIONS */
4927
4928_UA_END_DECLS
4929
4930
4931/**** amalgamated original file "/src/client/ua_client_internal.h" ****/
4932
4933/* This Source Code Form is subject to the terms of the Mozilla Public
4934 * License, v. 2.0. If a copy of the MPL was not distributed with this
4935 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4936 *
4937 * Copyright 2015-2016 (c) Sten Grüner
4938 * Copyright 2015-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
4939 * Copyright 2015 (c) Oleksiy Vasylyev
4940 * Copyright 2016-2017 (c) Florian Palm
4941 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
4942 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
4943 */
4944
4945
4946#define UA_INTERNAL
4947
4948
4949_UA_BEGIN_DECLS
4950
4951/**************************/
4952/* Subscriptions Handling */
4953/**************************/
4954
4955#ifdef UA_ENABLE_SUBSCRIPTIONS
4956
4957typedef struct UA_Client_NotificationsAckNumber {
4958 LIST_ENTRY(UA_Client_NotificationsAckNumber) listEntry;
4959 UA_SubscriptionAcknowledgement subAck;
4960} UA_Client_NotificationsAckNumber;
4961
4962typedef struct UA_Client_MonitoredItem {
4963 LIST_ENTRY(UA_Client_MonitoredItem) listEntry;
4964 UA_UInt32 monitoredItemId;
4965 UA_UInt32 clientHandle;
4966 void *context;
4967 UA_Client_DeleteMonitoredItemCallback deleteCallback;
4968 union {
4969 UA_Client_DataChangeNotificationCallback dataChangeCallback;
4970 UA_Client_EventNotificationCallback eventCallback;
4971 } handler;
4972 UA_Boolean isEventMonitoredItem; /* Otherwise a DataChange MoniitoredItem */
4973} UA_Client_MonitoredItem;
4974
4975typedef struct UA_Client_Subscription {
4976 LIST_ENTRY(UA_Client_Subscription) listEntry;
4977 UA_UInt32 subscriptionId;
4978 void *context;
4979 UA_Double publishingInterval;
4980 UA_UInt32 maxKeepAliveCount;
4981 UA_Client_StatusChangeNotificationCallback statusChangeCallback;
4982 UA_Client_DeleteSubscriptionCallback deleteCallback;
4983 UA_UInt32 sequenceNumber;
4984 UA_DateTime lastActivity;
4985 LIST_HEAD(, UA_Client_MonitoredItem) monitoredItems;
4986} UA_Client_Subscription;
4987
4988void
4989UA_Client_Subscriptions_clean(UA_Client *client);
4990
4991/* Exposed for fuzzing */
4992UA_StatusCode
4993UA_Client_preparePublishRequest(UA_Client *client, UA_PublishRequest *request);
4994
4995void
4996UA_Client_Subscriptions_backgroundPublish(UA_Client *client);
4997
4998void
4999UA_Client_Subscriptions_backgroundPublishInactivityCheck(UA_Client *client);
5000
5001#endif /* UA_ENABLE_SUBSCRIPTIONS */
5002
5003/**********/
5004/* Client */
5005/**********/
5006
5007typedef struct AsyncServiceCall {
5008 LIST_ENTRY(AsyncServiceCall) pointers;
5009 UA_UInt32 requestId;
5010 UA_ClientAsyncServiceCallback callback;
5011 const UA_DataType *responseType;
5012 void *userdata;
5013 UA_DateTime start;
5014 UA_UInt32 timeout;
5015 void *responsedata;
5016} AsyncServiceCall;
5017
5018void
5019UA_Client_AsyncService_cancel(UA_Client *client, AsyncServiceCall *ac,
5020 UA_StatusCode statusCode);
5021
5022void
5023UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode);
5024
5025typedef struct CustomCallback {
5026 UA_UInt32 callbackId;
5027
5028 UA_ClientAsyncServiceCallback userCallback;
5029 void *userData;
5030
5031 void *clientData;
5032} CustomCallback;
5033
5034struct UA_Client {
5035 UA_ClientConfig config;
5036 UA_Timer timer;
5037
5038 /* Overall connection status */
5039 UA_StatusCode connectStatus;
5040
5041 /* Old status to notify only changes */
5042 UA_SecureChannelState oldChannelState;
5043 UA_SessionState oldSessionState;
5044 UA_StatusCode oldConnectStatus;
5045
5046 UA_Boolean findServersHandshake; /* Ongoing FindServers */
5047 UA_Boolean endpointsHandshake; /* Ongoing GetEndpoints */
5048 UA_Boolean noSession; /* Don't open a session */
5049
5050 /* Connection */
5051 UA_Connection connection;
5052 UA_String endpointUrl; /* Used to extract address and port */
5053 UA_String discoveryUrl; /* The discoveryUrl (also used to signal which
5054 application we want to connect to in the HEL/ACK
5055 handshake). */
5056
5057 /* SecureChannel */
5058 UA_SecureChannel channel;
5059 UA_UInt32 requestId;
5060 UA_DateTime nextChannelRenewal;
5061
5062 /* Session */
5063 UA_SessionState sessionState;
5064 UA_NodeId authenticationToken;
5065 UA_UInt32 requestHandle;
5066 UA_ByteString remoteNonce;
5067 UA_ByteString localNonce;
5068
5069 /* Connectivity check */
5070 UA_DateTime lastConnectivityCheck;
5071 UA_Boolean pendingConnectivityCheck;
5072
5073 /* Async Service */
5074 LIST_HEAD(, AsyncServiceCall) asyncServiceCalls;
5075
5076 /* Subscriptions */
5077#ifdef UA_ENABLE_SUBSCRIPTIONS
5078 LIST_HEAD(, UA_Client_NotificationsAckNumber) pendingNotificationsAcks;
5079 LIST_HEAD(, UA_Client_Subscription) subscriptions;
5080 UA_UInt32 monitoredItemHandles;
5081 UA_UInt16 currentlyOutStandingPublishRequests;
5082#endif
5083};
5084
5085void notifyClientState(UA_Client *client);
5086void processERRResponse(UA_Client *client, const UA_ByteString *chunk);
5087void processACKResponse(UA_Client *client, const UA_ByteString *chunk);
5088void processOPNResponse(UA_Client *client, const UA_ByteString *message);
5089void closeSecureChannel(UA_Client *client);
5090
5091UA_StatusCode
5092connectIterate(UA_Client *client, UA_UInt32 timeout);
5093
5094UA_StatusCode
5095receiveResponseAsync(UA_Client *client, UA_UInt32 timeout);
5096
5097void
5098Client_warnEndpointsResult(UA_Client *client,
5099 const UA_GetEndpointsResponse *response,
5100 const UA_String *endpointUrl);
5101
5102_UA_END_DECLS
5103
5104
5105/**** amalgamated original file "/src/pubsub/ua_pubsub_config.h" ****/
5106
5107/* This Source Code Form is subject to the terms of the Mozilla Public
5108 * License, v. 2.0. If a copy of the MPL was not distributed with this
5109 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5110 *
5111 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
5112 * Copyright (c) 2020 Thomas Fischer, Siemens AG
5113 */
5114
5115#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
5116
5117
5118
5119/* Decodes the information from the ByteString. If the decoded content is a
5120 * PubSubConfiguration in a UABinaryFileDataType-object. It will overwrite the
5121 * current PubSub configuration from the server. */
5122UA_StatusCode
5123UA_PubSubManager_loadPubSubConfigFromByteString(UA_Server *server,
5124 const UA_ByteString buffer);
5125
5126/* Saves the current PubSub configuration of a server in a byteString. */
5127UA_StatusCode
5128UA_PubSubManager_getEncodedPubSubConfiguration(UA_Server *server,
5129 UA_ByteString *buffer);
5130
5131
5132#endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */
5133
5134/**** amalgamated original file "/build/src_generated/open62541/namespace0_generated.h" ****/
5135
5136/* WARNING: This is a generated file.
5137 * Any manual changes will be overwritten. */
5138
5139#ifndef NAMESPACE0_GENERATED_H_
5140#define NAMESPACE0_GENERATED_H_
5141
5142
5143#ifdef UA_ENABLE_AMALGAMATION
5144
5145/* The following declarations are in the open62541.c file so here's needed when compiling nodesets externally */
5146
5147# ifndef UA_INTERNAL //this definition is needed to hide this code in the amalgamated .c file
5148
5149typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos,
5150 const UA_Byte **bufEnd);
5151
5152UA_StatusCode
5153UA_encodeBinary(const void *src, const UA_DataType *type,
5154 UA_Byte **bufPos, const UA_Byte **bufEnd,
5155 UA_exchangeEncodeBuffer exchangeCallback,
5156 void *exchangeHandle) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
5157
5158UA_StatusCode
5159UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
5160 const UA_DataType *type, size_t customTypesSize,
5161 const UA_DataType *customTypes) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
5162
5163size_t
5164UA_calcSizeBinary(void *p, const UA_DataType *type);
5165
5166const UA_DataType *
5167UA_findDataTypeByBinary(const UA_NodeId *typeId);
5168
5169# endif // UA_INTERNAL
5170
5171#else // UA_ENABLE_AMALGAMATION
5172#endif
5173
5174
5175
5176
5177_UA_BEGIN_DECLS
5178
5179extern UA_StatusCode namespace0_generated(UA_Server *server);
5180
5181_UA_END_DECLS
5182
5183#endif /* NAMESPACE0_GENERATED_H_ */
5184
5185/**** amalgamated original file "/src/ua_types.c" ****/
5186
5187/* This Source Code Form is subject to the terms of the Mozilla Public
5188 * License, v. 2.0. If a copy of the MPL was not distributed with this
5189 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5190 *
5191 * Copyright 2020 (c) Fraunhofer IOSB (Author: Andreas Ebner)
5192 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
5193 * Copyright 2014, 2016-2017 (c) Florian Palm
5194 * Copyright 2014-2016 (c) Sten Grüner
5195 * Copyright 2014 (c) Leon Urbas
5196 * Copyright 2015 (c) Chris Iatrou
5197 * Copyright 2015 (c) Markus Graube
5198 * Copyright 2015 (c) Reza Ebrahimi
5199 * Copyright 2015-2016 (c) Oleksiy Vasylyev
5200 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
5201 * Copyright 2016 (c) Lorenz Haas
5202 */
5203
5204
5205
5206#define UA_MAX_ARRAY_DIMS 100 /* Max dimensions of an array */
5207
5208/* Datatype Handling
5209 * -----------------
5210 * This file contains handling functions for the builtin types and functions
5211 * handling of structured types and arrays. These need type descriptions in a
5212 * UA_DataType structure. The UA_DataType structures as well as all non-builtin
5213 * datatypes are autogenerated. */
5214
5215/* Global definition of NULL type instances. These are always zeroed out, as
5216 * mandated by the C/C++ standard for global values with no initializer. */
5217const UA_String UA_STRING_NULL = {0};
5218const UA_ByteString UA_BYTESTRING_NULL = {0};
5219const UA_Guid UA_GUID_NULL = {0};
5220const UA_NodeId UA_NODEID_NULL = {0};
5221const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {0};
5222
5223typedef UA_StatusCode
5224(*UA_copySignature)(const void *src, void *dst, const UA_DataType *type);
5225extern const UA_copySignature copyJumpTable[UA_DATATYPEKINDS];
5226
5227typedef void (*UA_clearSignature)(void *p, const UA_DataType *type);
5228extern const UA_clearSignature clearJumpTable[UA_DATATYPEKINDS];
5229
5230typedef UA_Order
5231(*UA_orderSignature)(const void *p1, const void *p2, const UA_DataType *type);
5232extern const UA_orderSignature orderJumpTable[UA_DATATYPEKINDS];
5233
5234const UA_DataType *
5235UA_findDataTypeWithCustom(const UA_NodeId *typeId,
5236 const UA_DataTypeArray *customTypes) {
5237 /* Always look in built-in types first (may contain data types from all
5238 * namespaces).
5239 *
5240 * TODO: The standard-defined types are ordered. See if binary search is
5241 * more efficient. */
5242 for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
5243 if(UA_NodeId_equal(n1: &UA_TYPES[i].typeId, n2: typeId))
5244 return &UA_TYPES[i];
5245 }
5246
5247 /* Search in the customTypes */
5248 while(customTypes) {
5249 for(size_t i = 0; i < customTypes->typesSize; ++i) {
5250 if(UA_NodeId_equal(n1: &customTypes->types[i].typeId, n2: typeId))
5251 return &customTypes->types[i];
5252 }
5253 customTypes = customTypes->next;
5254 }
5255
5256 return NULL;
5257}
5258
5259const UA_DataType *
5260UA_findDataType(const UA_NodeId *typeId) {
5261 return UA_findDataTypeWithCustom(typeId, NULL);
5262}
5263
5264/***************************/
5265/* Random Number Generator */
5266/***************************/
5267
5268//TODO is this safe for multithreading?
5269static pcg32_random_t UA_rng = PCG32_INITIALIZER;
5270
5271void
5272UA_random_seed(u64 seed) {
5273 pcg32_srandom_r(rng: &UA_rng, initial_state: seed, initseq: (u64)UA_DateTime_now());
5274}
5275
5276u32
5277UA_UInt32_random(void) {
5278 return (u32)pcg32_random_r(rng: &UA_rng);
5279}
5280
5281/*****************/
5282/* Builtin Types */
5283/*****************/
5284
5285UA_String
5286UA_String_fromChars(const char *src) {
5287 UA_String s; s.length = 0; s.data = NULL;
5288 if(!src)
5289 return s;
5290 s.length = strlen(s: src);
5291 if(s.length > 0) {
5292 s.data = (u8*)UA_malloc(size: s.length);
5293 if(UA_UNLIKELY(!s.data)) {
5294 s.length = 0;
5295 return s;
5296 }
5297 memcpy(dest: s.data, src: src, n: s.length);
5298 } else {
5299 s.data = (u8*)UA_EMPTY_ARRAY_SENTINEL;
5300 }
5301 return s;
5302}
5303
5304static UA_Order
5305stringOrder(const UA_String *p1, const UA_String *p2, const UA_DataType *type);
5306static UA_Order
5307guidOrder(const UA_Guid *p1, const UA_Guid *p2, const UA_DataType *type);
5308static UA_Order
5309qualifiedNameOrder(const UA_QualifiedName *p1, const UA_QualifiedName *p2,
5310 const UA_DataType *type);
5311
5312UA_Boolean
5313UA_String_equal(const UA_String *s1, const UA_String *s2) {
5314 return (stringOrder(p1: s1, p2: s2, NULL) == UA_ORDER_EQ);
5315}
5316
5317/* Do not expose UA_String_equal_ignorecase to public API as it currently only handles
5318 * ASCII strings, and not UTF8! */
5319UA_Boolean
5320UA_String_equal_ignorecase(const UA_String *s1, const UA_String *s2) {
5321 if(s1->length != s2->length)
5322 return false;
5323 if(s1->length == 0)
5324 return true;
5325 if(s2->data == NULL)
5326 return false;
5327
5328 //FIXME this currently does not handle UTF8
5329 return UA_strncasecmp(s1: (const char*)s1->data, s2: (const char*)s2->data, n: s1->length) == 0;
5330}
5331
5332static UA_StatusCode
5333String_copy(UA_String const *src, UA_String *dst, const UA_DataType *_) {
5334 UA_StatusCode res =
5335 UA_Array_copy(src: src->data, size: src->length, dst: (void**)&dst->data,
5336 type: &UA_TYPES[UA_TYPES_BYTE]);
5337 if(res == UA_STATUSCODE_GOOD)
5338 dst->length = src->length;
5339 return res;
5340}
5341
5342static void
5343String_clear(UA_String *s, const UA_DataType *_) {
5344 UA_Array_delete(p: s->data, size: s->length, type: &UA_TYPES[UA_TYPES_BYTE]);
5345}
5346
5347/* QualifiedName */
5348static UA_StatusCode
5349QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst,
5350 const UA_DataType *_) {
5351 dst->namespaceIndex = src->namespaceIndex;
5352 return String_copy(src: &src->name, dst: &dst->name, NULL);
5353}
5354
5355static void
5356QualifiedName_clear(UA_QualifiedName *p, const UA_DataType *_) {
5357 String_clear(s: &p->name, NULL);
5358}
5359
5360u32
5361UA_QualifiedName_hash(const UA_QualifiedName *q) {
5362 return UA_ByteString_hash(initialHashValue: q->namespaceIndex,
5363 data: q->name.data, size: q->name.length);
5364}
5365
5366UA_Boolean
5367UA_QualifiedName_equal(const UA_QualifiedName *qn1,
5368 const UA_QualifiedName *qn2) {
5369 return (qualifiedNameOrder(p1: qn1, p2: qn2, NULL) == UA_ORDER_EQ);
5370}
5371
5372/* DateTime */
5373UA_DateTimeStruct
5374UA_DateTime_toStruct(UA_DateTime t) {
5375 /* Divide, then subtract -> avoid underflow. Also, negative numbers are
5376 * rounded up, not down. */
5377 long long secSinceUnixEpoch = (long long)(t / UA_DATETIME_SEC)
5378 - (long long)(UA_DATETIME_UNIX_EPOCH / UA_DATETIME_SEC);
5379
5380 /* Negative fractions of a second? Remove one full second from the epoch
5381 * distance and allow only a positive fraction. */
5382 UA_DateTime frac = t % UA_DATETIME_SEC;
5383 if(frac < 0) {
5384 secSinceUnixEpoch--;
5385 frac += UA_DATETIME_SEC;
5386 }
5387
5388 struct mytm ts;
5389 memset(s: &ts, c: 0, n: sizeof(struct mytm));
5390 __secs_to_tm(t: secSinceUnixEpoch, tm: &ts);
5391
5392 UA_DateTimeStruct dateTimeStruct;
5393 dateTimeStruct.year = (i16)(ts.tm_year + 1900);
5394 dateTimeStruct.month = (u16)(ts.tm_mon + 1);
5395 dateTimeStruct.day = (u16)ts.tm_mday;
5396 dateTimeStruct.hour = (u16)ts.tm_hour;
5397 dateTimeStruct.min = (u16)ts.tm_min;
5398 dateTimeStruct.sec = (u16)ts.tm_sec;
5399 dateTimeStruct.milliSec = (u16)((frac % 10000000) / 10000);
5400 dateTimeStruct.microSec = (u16)((frac % 10000) / 10);
5401 dateTimeStruct.nanoSec = (u16)((frac % 10) * 100);
5402 return dateTimeStruct;
5403}
5404
5405UA_DateTime
5406UA_DateTime_fromStruct(UA_DateTimeStruct ts) {
5407 /* Seconds since the Unix epoch */
5408 struct mytm tm;
5409 memset(s: &tm, c: 0, n: sizeof(struct mytm));
5410 tm.tm_year = ts.year - 1900;
5411 tm.tm_mon = ts.month - 1;
5412 tm.tm_mday = ts.day;
5413 tm.tm_hour = ts.hour;
5414 tm.tm_min = ts.min;
5415 tm.tm_sec = ts.sec;
5416 long long sec_epoch = __tm_to_secs(tm: &tm);
5417
5418 UA_DateTime t = UA_DATETIME_UNIX_EPOCH;
5419 t += sec_epoch * UA_DATETIME_SEC;
5420 t += ts.milliSec * UA_DATETIME_MSEC;
5421 t += ts.microSec * UA_DATETIME_USEC;
5422 t += ts.nanoSec / 100;
5423 return t;
5424}
5425
5426/* Guid */
5427UA_Boolean
5428UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
5429 return (guidOrder(p1: g1, p2: g2, NULL) == UA_ORDER_EQ);
5430}
5431
5432UA_Guid
5433UA_Guid_random(void) {
5434 UA_Guid result;
5435 result.data1 = (u32)pcg32_random_r(rng: &UA_rng);
5436 u32 r = (u32)pcg32_random_r(rng: &UA_rng);
5437 result.data2 = (u16) r;
5438 result.data3 = (u16) (r >> 16);
5439 r = (u32)pcg32_random_r(rng: &UA_rng);
5440 result.data4[0] = (u8)r;
5441 result.data4[1] = (u8)(r >> 4);
5442 result.data4[2] = (u8)(r >> 8);
5443 result.data4[3] = (u8)(r >> 12);
5444 r = (u32)pcg32_random_r(rng: &UA_rng);
5445 result.data4[4] = (u8)r;
5446 result.data4[5] = (u8)(r >> 4);
5447 result.data4[6] = (u8)(r >> 8);
5448 result.data4[7] = (u8)(r >> 12);
5449 return result;
5450}
5451
5452/* ByteString */
5453UA_StatusCode
5454UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length) {
5455 UA_ByteString_init(p: bs);
5456 if(length == 0)
5457 return UA_STATUSCODE_GOOD;
5458 bs->data = (u8*)UA_malloc(size: length);
5459 if(UA_UNLIKELY(!bs->data))
5460 return UA_STATUSCODE_BADOUTOFMEMORY;
5461 bs->length = length;
5462 return UA_STATUSCODE_GOOD;
5463}
5464
5465/* NodeId */
5466static void
5467NodeId_clear(UA_NodeId *p, const UA_DataType *_) {
5468 switch(p->identifierType) {
5469 case UA_NODEIDTYPE_STRING:
5470 case UA_NODEIDTYPE_BYTESTRING:
5471 String_clear(s: &p->identifier.string, NULL);
5472 break;
5473 default: break;
5474 }
5475}
5476
5477static UA_StatusCode
5478NodeId_copy(UA_NodeId const *src, UA_NodeId *dst, const UA_DataType *_) {
5479 UA_StatusCode retval = UA_STATUSCODE_GOOD;
5480 switch(src->identifierType) {
5481 case UA_NODEIDTYPE_NUMERIC:
5482 *dst = *src;
5483 return UA_STATUSCODE_GOOD;
5484 case UA_NODEIDTYPE_STRING:
5485 case UA_NODEIDTYPE_BYTESTRING:
5486 retval |= String_copy(src: &src->identifier.string,
5487 dst: &dst->identifier.string, NULL);
5488 break;
5489 case UA_NODEIDTYPE_GUID:
5490 dst->identifier.guid = src->identifier.guid;
5491 break;
5492 default:
5493 return UA_STATUSCODE_BADINTERNALERROR;
5494 }
5495 dst->namespaceIndex = src->namespaceIndex;
5496 dst->identifierType = src->identifierType;
5497 return retval;
5498}
5499
5500UA_Boolean
5501UA_NodeId_isNull(const UA_NodeId *p) {
5502 if(p->namespaceIndex != 0)
5503 return false;
5504 switch (p->identifierType) {
5505 case UA_NODEIDTYPE_NUMERIC:
5506 return (p->identifier.numeric == 0);
5507 case UA_NODEIDTYPE_STRING:
5508 case UA_NODEIDTYPE_BYTESTRING:
5509 return (p->identifier.string.length == 0); /* Null and empty string */
5510 case UA_NODEIDTYPE_GUID:
5511 return UA_Guid_equal(g1: &p->identifier.guid, g2: &UA_GUID_NULL);
5512 }
5513 return false;
5514}
5515
5516/* Absolute ordering for NodeIds */
5517UA_Order
5518UA_NodeId_order(const UA_NodeId *n1, const UA_NodeId *n2) {
5519 /* Compare namespaceIndex */
5520 if(n1->namespaceIndex != n2->namespaceIndex)
5521 return (n1->namespaceIndex < n2->namespaceIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
5522
5523 /* Compare identifierType */
5524 if(n1->identifierType != n2->identifierType)
5525 return (n1->identifierType < n2->identifierType) ? UA_ORDER_LESS : UA_ORDER_MORE;
5526
5527 /* Compare the identifier */
5528 switch(n1->identifierType) {
5529 case UA_NODEIDTYPE_NUMERIC:
5530 default:
5531 if(n1->identifier.numeric != n2->identifier.numeric)
5532 return (n1->identifier.numeric < n2->identifier.numeric) ?
5533 UA_ORDER_LESS : UA_ORDER_MORE;
5534 return UA_ORDER_EQ;
5535
5536 case UA_NODEIDTYPE_GUID:
5537 return guidOrder(p1: &n1->identifier.guid, p2: &n2->identifier.guid, NULL);
5538
5539 case UA_NODEIDTYPE_STRING:
5540 case UA_NODEIDTYPE_BYTESTRING:
5541 return stringOrder(p1: &n1->identifier.string, p2: &n2->identifier.string, NULL);
5542 }
5543}
5544
5545/* sdbm-hash (http://www.cse.yorku.ca/~oz/hash.html) */
5546u32
5547UA_ByteString_hash(u32 initialHashValue,
5548 const u8 *data, size_t size) {
5549 u32 h = initialHashValue;
5550 for(size_t i = 0; i < size; i++)
5551 h = data[i] + (h << 6) + (h << 16) - h;
5552 return h;
5553}
5554
5555u32
5556UA_NodeId_hash(const UA_NodeId *n) {
5557 switch(n->identifierType) {
5558 case UA_NODEIDTYPE_NUMERIC:
5559 default:
5560 return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: (const u8*)&n->identifier.numeric,
5561 size: sizeof(UA_UInt32));
5562 case UA_NODEIDTYPE_STRING:
5563 case UA_NODEIDTYPE_BYTESTRING:
5564 return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: n->identifier.string.data,
5565 size: n->identifier.string.length);
5566 case UA_NODEIDTYPE_GUID:
5567 return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: (const u8*)&n->identifier.guid,
5568 size: sizeof(UA_Guid));
5569 }
5570}
5571
5572/* ExpandedNodeId */
5573static void
5574ExpandedNodeId_clear(UA_ExpandedNodeId *p, const UA_DataType *_) {
5575 NodeId_clear(p: &p->nodeId, _);
5576 String_clear(s: &p->namespaceUri, NULL);
5577}
5578
5579static UA_StatusCode
5580ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst,
5581 const UA_DataType *_) {
5582 UA_StatusCode retval = NodeId_copy(src: &src->nodeId, dst: &dst->nodeId, NULL);
5583 retval |= String_copy(src: &src->namespaceUri, dst: &dst->namespaceUri, NULL);
5584 dst->serverIndex = src->serverIndex;
5585 return retval;
5586}
5587
5588UA_Boolean
5589UA_ExpandedNodeId_isLocal(const UA_ExpandedNodeId *n) {
5590 return (n->namespaceUri.length == 0 && n->serverIndex == 0);
5591}
5592
5593UA_Order
5594UA_ExpandedNodeId_order(const UA_ExpandedNodeId *n1,
5595 const UA_ExpandedNodeId *n2) {
5596 if(n1->serverIndex != n2->serverIndex)
5597 return (n1->serverIndex < n2->serverIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
5598 UA_Order o = stringOrder(p1: &n1->namespaceUri, p2: &n2->namespaceUri, NULL);
5599 if(o != UA_ORDER_EQ)
5600 return o;
5601 return UA_NodeId_order(n1: &n1->nodeId, n2: &n2->nodeId);
5602}
5603
5604u32
5605UA_ExpandedNodeId_hash(const UA_ExpandedNodeId *n) {
5606 u32 h = UA_NodeId_hash(n: &n->nodeId);
5607 if(n->serverIndex != 0)
5608 h = UA_ByteString_hash(initialHashValue: h, data: (const UA_Byte*)&n->serverIndex, size: 4);
5609 if(n->namespaceUri.length != 0)
5610 h = UA_ByteString_hash(initialHashValue: h, data: n->namespaceUri.data, size: n->namespaceUri.length);
5611 return h;
5612}
5613
5614/* ExtensionObject */
5615static void
5616ExtensionObject_clear(UA_ExtensionObject *p, const UA_DataType *_) {
5617 switch(p->encoding) {
5618 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
5619 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
5620 case UA_EXTENSIONOBJECT_ENCODED_XML:
5621 NodeId_clear(p: &p->content.encoded.typeId, NULL);
5622 String_clear(s: &p->content.encoded.body, NULL);
5623 break;
5624 case UA_EXTENSIONOBJECT_DECODED:
5625 if(p->content.decoded.data)
5626 UA_delete(p: p->content.decoded.data, type: p->content.decoded.type);
5627 break;
5628 default:
5629 break;
5630 }
5631}
5632
5633static UA_StatusCode
5634ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst,
5635 const UA_DataType *_) {
5636 UA_StatusCode retval = UA_STATUSCODE_GOOD;
5637 switch(src->encoding) {
5638 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
5639 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
5640 case UA_EXTENSIONOBJECT_ENCODED_XML:
5641 dst->encoding = src->encoding;
5642 retval = NodeId_copy(src: &src->content.encoded.typeId,
5643 dst: &dst->content.encoded.typeId, NULL);
5644 /* ByteString -> copy as string */
5645 retval |= String_copy(src: &src->content.encoded.body,
5646 dst: &dst->content.encoded.body, NULL);
5647 break;
5648 case UA_EXTENSIONOBJECT_DECODED:
5649 case UA_EXTENSIONOBJECT_DECODED_NODELETE:
5650 if(!src->content.decoded.type || !src->content.decoded.data)
5651 return UA_STATUSCODE_BADINTERNALERROR;
5652 dst->encoding = UA_EXTENSIONOBJECT_DECODED;
5653 dst->content.decoded.type = src->content.decoded.type;
5654 retval = UA_Array_copy(src: src->content.decoded.data, size: 1,
5655 dst: &dst->content.decoded.data, type: src->content.decoded.type);
5656 break;
5657 default:
5658 break;
5659 }
5660 return retval;
5661}
5662
5663void
5664UA_ExtensionObject_setValue(UA_ExtensionObject *eo,
5665 void * UA_RESTRICT p,
5666 const UA_DataType *type) {
5667 UA_ExtensionObject_init(p: eo);
5668 eo->content.decoded.data = p;
5669 eo->content.decoded.type = type;
5670 eo->encoding = UA_EXTENSIONOBJECT_DECODED;
5671}
5672
5673void
5674UA_ExtensionObject_setValueNoDelete(UA_ExtensionObject *eo,
5675 void * UA_RESTRICT p,
5676 const UA_DataType *type) {
5677 UA_ExtensionObject_init(p: eo);
5678 eo->content.decoded.data = p;
5679 eo->content.decoded.type = type;
5680 eo->encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
5681}
5682
5683UA_StatusCode
5684UA_ExtensionObject_setValueCopy(UA_ExtensionObject *eo,
5685 void * UA_RESTRICT p,
5686 const UA_DataType *type) {
5687 UA_ExtensionObject_init(p: eo);
5688
5689 /* Make a copy of the value */
5690 void *val = UA_malloc(size: type->memSize);
5691 if(UA_UNLIKELY(!val))
5692 return UA_STATUSCODE_BADOUTOFMEMORY;
5693 UA_StatusCode res = UA_copy(src: p, dst: val, type);
5694 if(UA_UNLIKELY(res != UA_STATUSCODE_GOOD)) {
5695 UA_free(ptr: val);
5696 return res;
5697 }
5698
5699 /* Set the ExtensionObject */
5700 eo->content.decoded.data = val;
5701 eo->content.decoded.type = type;
5702 eo->encoding = UA_EXTENSIONOBJECT_DECODED;
5703 return UA_STATUSCODE_GOOD;
5704}
5705
5706/* Variant */
5707static void
5708Variant_clear(UA_Variant *p, const UA_DataType *_) {
5709 /* The content is "borrowed" */
5710 if(p->storageType == UA_VARIANT_DATA_NODELETE)
5711 return;
5712
5713 /* Delete the value */
5714 if(p->type && p->data > UA_EMPTY_ARRAY_SENTINEL) {
5715 if(p->arrayLength == 0)
5716 p->arrayLength = 1;
5717 UA_Array_delete(p: p->data, size: p->arrayLength, type: p->type);
5718 p->data = NULL;
5719 }
5720
5721 /* Delete the array dimensions */
5722 if((void*)p->arrayDimensions > UA_EMPTY_ARRAY_SENTINEL)
5723 UA_free(ptr: p->arrayDimensions);
5724}
5725
5726static UA_StatusCode
5727Variant_copy(UA_Variant const *src, UA_Variant *dst, const UA_DataType *_) {
5728 size_t length = src->arrayLength;
5729 if(UA_Variant_isScalar(v: src))
5730 length = 1;
5731 UA_StatusCode retval = UA_Array_copy(src: src->data, size: length,
5732 dst: &dst->data, type: src->type);
5733 if(retval != UA_STATUSCODE_GOOD)
5734 return retval;
5735 dst->arrayLength = src->arrayLength;
5736 dst->type = src->type;
5737 if(src->arrayDimensions) {
5738 retval = UA_Array_copy(src: src->arrayDimensions, size: src->arrayDimensionsSize,
5739 dst: (void**)&dst->arrayDimensions, type: &UA_TYPES[UA_TYPES_INT32]);
5740 if(retval != UA_STATUSCODE_GOOD)
5741 return retval;
5742 dst->arrayDimensionsSize = src->arrayDimensionsSize;
5743 }
5744 return UA_STATUSCODE_GOOD;
5745}
5746
5747void
5748UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p,
5749 const UA_DataType *type) {
5750 UA_Variant_init(p: v);
5751 v->type = type;
5752 v->arrayLength = 0;
5753 v->data = p;
5754}
5755
5756UA_StatusCode
5757UA_Variant_setScalarCopy(UA_Variant *v, const void * UA_RESTRICT p,
5758 const UA_DataType *type) {
5759 void *n = UA_malloc(size: type->memSize);
5760 if(UA_UNLIKELY(!n))
5761 return UA_STATUSCODE_BADOUTOFMEMORY;
5762 UA_StatusCode retval = UA_copy(src: p, dst: n, type);
5763 if(UA_UNLIKELY(retval != UA_STATUSCODE_GOOD)) {
5764 UA_free(ptr: n);
5765 //cppcheck-suppress memleak
5766 return retval;
5767 }
5768 UA_Variant_setScalar(v, p: n, type);
5769 //cppcheck-suppress memleak
5770 return UA_STATUSCODE_GOOD;
5771}
5772
5773void UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
5774 size_t arraySize, const UA_DataType *type) {
5775 UA_Variant_init(p: v);
5776 v->data = array;
5777 v->arrayLength = arraySize;
5778 v->type = type;
5779}
5780
5781UA_StatusCode
5782UA_Variant_setArrayCopy(UA_Variant *v, const void * UA_RESTRICT array,
5783 size_t arraySize, const UA_DataType *type) {
5784 UA_Variant_init(p: v);
5785 UA_StatusCode retval = UA_Array_copy(src: array, size: arraySize, dst: &v->data, type);
5786 if(retval != UA_STATUSCODE_GOOD)
5787 return retval;
5788 v->arrayLength = arraySize;
5789 v->type = type;
5790 return UA_STATUSCODE_GOOD;
5791}
5792
5793/* Test if a range is compatible with a variant. This may adjust the upper bound
5794 * (max) in order to fit the variant. */
5795static UA_StatusCode
5796checkAdjustRange(const UA_Variant *v, UA_NumericRange *range) {
5797 /* Test for max array size (64bit only) */
5798#if (SIZE_MAX > 0xffffffff)
5799 if(v->arrayLength > UA_UINT32_MAX)
5800 return UA_STATUSCODE_BADINTERNALERROR;
5801#endif
5802 u32 arrayLength = (u32)v->arrayLength;
5803
5804 /* Assume one array dimension if none defined */
5805 const u32 *dims = v->arrayDimensions;
5806 size_t dims_count = v->arrayDimensionsSize;
5807 if(v->arrayDimensionsSize == 0) {
5808 dims_count = 1;
5809 dims = &arrayLength;
5810 }
5811
5812 /* Does the range match the dimension of the variant? */
5813 if(range->dimensionsSize != dims_count)
5814 return UA_STATUSCODE_BADINDEXRANGENODATA;
5815
5816 /* Check that the number of elements in the variant matches the array
5817 * dimensions */
5818 size_t elements = 1;
5819 for(size_t i = 0; i < dims_count; ++i)
5820 elements *= dims[i];
5821 if(elements != v->arrayLength)
5822 return UA_STATUSCODE_BADINTERNALERROR;
5823
5824 /* Test the integrity of the range and compute the max index used for every
5825 * dimension. The standard says in Part 4, Section 7.22:
5826 *
5827 * When reading a value, the indexes may not specify a range that is within
5828 * the bounds of the array. The Server shall return a partial result if some
5829 * elements exist within the range. */
5830 for(size_t i = 0; i < dims_count; ++i) {
5831 if(range->dimensions[i].min > range->dimensions[i].max)
5832 return UA_STATUSCODE_BADINDEXRANGEINVALID;
5833 if(range->dimensions[i].min >= dims[i])
5834 return UA_STATUSCODE_BADINDEXRANGENODATA;
5835
5836 /* Reduce the max to fit the variant */
5837 if(range->dimensions[i].max >= dims[i])
5838 range->dimensions[i].max = dims[i] - 1;
5839 }
5840
5841 return UA_STATUSCODE_GOOD;
5842}
5843
5844/* Computes the stride for copying the range elements.
5845 * - total: how many elements are in the range
5846 * - block: how big is each contiguous block of elements in the variant that
5847 * maps into the range
5848 * - stride: how many elements are between the blocks (beginning to beginning)
5849 * - first: where does the first block begin */
5850static void
5851computeStrides(const UA_Variant *v, const UA_NumericRange range,
5852 size_t *total, size_t *block, size_t *stride, size_t *first) {
5853 /* Number of total elements to be copied */
5854 size_t count = 1;
5855 for(size_t i = 0; i < range.dimensionsSize; ++i)
5856 count *= (range.dimensions[i].max - range.dimensions[i].min) + 1;
5857 *total = count;
5858
5859 /* Assume one array dimension if none defined */
5860 u32 arrayLength = (u32)v->arrayLength;
5861 const u32 *dims = v->arrayDimensions;
5862 size_t dims_count = v->arrayDimensionsSize;
5863 if(v->arrayDimensionsSize == 0) {
5864 dims_count = 1;
5865 dims = &arrayLength;
5866 }
5867
5868 /* Compute the stride length and the position of the first element */
5869 *block = count; /* Assume the range describes the entire array. */
5870 *stride = v->arrayLength; /* So it can be copied as a contiguous block. */
5871 *first = 0;
5872 size_t running_dimssize = 1;
5873 UA_Boolean found_contiguous = false;
5874 for(size_t k = dims_count; k > 0;) {
5875 --k;
5876 size_t dimrange = 1 + range.dimensions[k].max - range.dimensions[k].min;
5877 if(!found_contiguous && dimrange != dims[k]) {
5878 /* Found the maximum block that can be copied contiguously */
5879 found_contiguous = true;
5880 *block = running_dimssize * dimrange;
5881 *stride = running_dimssize * dims[k];
5882 }
5883 *first += running_dimssize * range.dimensions[k].min;
5884 running_dimssize *= dims[k];
5885 }
5886}
5887
5888/* Is the type string-like? */
5889static UA_Boolean
5890isStringLike(const UA_DataType *type) {
5891 if(type == &UA_TYPES[UA_TYPES_STRING] ||
5892 type == &UA_TYPES[UA_TYPES_BYTESTRING] ||
5893 type == &UA_TYPES[UA_TYPES_XMLELEMENT])
5894 return true;
5895 return false;
5896}
5897
5898/* Returns the part of the string that lies within the rangedimension */
5899static UA_StatusCode
5900copySubString(const UA_String *src, UA_String *dst,
5901 const UA_NumericRangeDimension *dim) {
5902 if(dim->min > dim->max)
5903 return UA_STATUSCODE_BADINDEXRANGEINVALID;
5904 if(dim->min >= src->length)
5905 return UA_STATUSCODE_BADINDEXRANGENODATA;
5906
5907 size_t length;
5908 if(dim->max < src->length)
5909 length = dim->max - dim->min + 1;
5910 else
5911 length = src->length - dim->min;
5912
5913 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: dst, length);
5914 if(retval != UA_STATUSCODE_GOOD)
5915 return retval;
5916
5917 memcpy(dest: dst->data, src: &src->data[dim->min], n: length);
5918 return UA_STATUSCODE_GOOD;
5919}
5920
5921UA_StatusCode
5922UA_Variant_copyRange(const UA_Variant *src, UA_Variant * UA_RESTRICT dst,
5923 const UA_NumericRange range) {
5924 if(!src->type)
5925 return UA_STATUSCODE_BADINVALIDARGUMENT;
5926
5927 UA_Boolean isScalar = UA_Variant_isScalar(v: src);
5928 UA_Boolean stringLike = isStringLike(type: src->type);
5929
5930 /* Upper bound of the dimensions for stack-allocation */
5931 if(range.dimensionsSize > UA_MAX_ARRAY_DIMS)
5932 return UA_STATUSCODE_BADINTERNALERROR;
5933
5934 /* Copy the const range to a mutable stack location */
5935 UA_NumericRangeDimension thisrangedims[UA_MAX_ARRAY_DIMS];
5936 memcpy(dest: thisrangedims, src: range.dimensions, n: sizeof(UA_NumericRangeDimension) * range.dimensionsSize);
5937 UA_NumericRange thisrange = {range.dimensionsSize, thisrangedims};
5938
5939 UA_NumericRangeDimension scalarThisDimension = {0,0}; /* a single entry */
5940 UA_NumericRange nextrange = {0, NULL};
5941
5942 /* Extract the range for copying at this level. The remaining range is dealt
5943 * with in the "scalar" type that may define an array by itself (string,
5944 * variant, ...). */
5945 UA_Variant arraySrc;
5946 if(isScalar) {
5947 /* Replace scalar src with array of length 1 */
5948 arraySrc = *src;
5949 arraySrc.arrayLength = 1;
5950 src = &arraySrc;
5951 /* Deal with all range dimensions within the scalar */
5952 thisrange.dimensions = &scalarThisDimension;
5953 thisrange.dimensionsSize = 1;
5954 nextrange = range;
5955 } else {
5956 /* Deal with as many range dimensions as possible right now */
5957 size_t dims = src->arrayDimensionsSize;
5958 if(dims == 0)
5959 dims = 1;
5960 if(dims > range.dimensionsSize)
5961 return UA_STATUSCODE_BADINDEXRANGEINVALID;
5962 thisrange.dimensionsSize = dims;
5963 nextrange.dimensions = &range.dimensions[dims];
5964 nextrange.dimensionsSize = range.dimensionsSize - dims;
5965 }
5966
5967 UA_StatusCode retval = checkAdjustRange(v: src, range: &thisrange);
5968 if(retval != UA_STATUSCODE_GOOD)
5969 return retval;
5970
5971 /* Compute the strides */
5972 size_t count, block, stride, first;
5973 computeStrides(v: src, range: thisrange, total: &count, block: &block, stride: &stride, first: &first);
5974
5975 /* Allocate the array */
5976 UA_Variant_init(p: dst);
5977 dst->data = UA_Array_new(size: count, type: src->type);
5978 if(!dst->data)
5979 return UA_STATUSCODE_BADOUTOFMEMORY;
5980
5981 /* Copy the range */
5982 size_t block_count = count / block;
5983 size_t elem_size = src->type->memSize;
5984 uintptr_t nextdst = (uintptr_t)dst->data;
5985 uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first);
5986 if(nextrange.dimensionsSize == 0) {
5987 /* no nextrange */
5988 if(src->type->pointerFree) {
5989 for(size_t i = 0; i < block_count; ++i) {
5990 memcpy(dest: (void*)nextdst, src: (void*)nextsrc, n: elem_size * block);
5991 nextdst += block * elem_size;
5992 nextsrc += stride * elem_size;
5993 }
5994 } else {
5995 for(size_t i = 0; i < block_count; ++i) {
5996 for(size_t j = 0; j < block; ++j) {
5997 retval = UA_copy(src: (const void*)nextsrc,
5998 dst: (void*)nextdst, type: src->type);
5999 nextdst += elem_size;
6000 nextsrc += elem_size;
6001 }
6002 nextsrc += (stride - block) * elem_size;
6003 }
6004 }
6005 } else {
6006 /* nextrange can only be used for variants and stringlike with remaining
6007 * range of dimension 1 */
6008 if(src->type != &UA_TYPES[UA_TYPES_VARIANT]) {
6009 if(!stringLike)
6010 retval = UA_STATUSCODE_BADINDEXRANGENODATA;
6011 if(nextrange.dimensionsSize != 1)
6012 retval = UA_STATUSCODE_BADINDEXRANGENODATA;
6013 }
6014
6015 /* Copy the content */
6016 for(size_t i = 0; i < block_count; ++i) {
6017 for(size_t j = 0; j < block && retval == UA_STATUSCODE_GOOD; ++j) {
6018 if(stringLike)
6019 retval = copySubString(src: (const UA_String*)nextsrc,
6020 dst: (UA_String*)nextdst,
6021 dim: nextrange.dimensions);
6022 else
6023 retval = UA_Variant_copyRange(src: (const UA_Variant*)nextsrc,
6024 dst: (UA_Variant*)nextdst,
6025 range: nextrange);
6026 nextdst += elem_size;
6027 nextsrc += elem_size;
6028 }
6029 nextsrc += (stride - block) * elem_size;
6030 }
6031 }
6032
6033 /* Clean up if copying failed */
6034 if(retval != UA_STATUSCODE_GOOD) {
6035 UA_Array_delete(p: dst->data, size: count, type: src->type);
6036 dst->data = NULL;
6037 return retval;
6038 }
6039
6040 /* Done if scalar */
6041 dst->type = src->type;
6042 if(isScalar)
6043 return retval;
6044
6045 /* Copy array dimensions */
6046 dst->arrayLength = count;
6047 if(src->arrayDimensionsSize > 0) {
6048 dst->arrayDimensions =
6049 (u32*)UA_Array_new(size: thisrange.dimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]);
6050 if(!dst->arrayDimensions) {
6051 Variant_clear(p: dst, NULL);
6052 return UA_STATUSCODE_BADOUTOFMEMORY;
6053 }
6054 dst->arrayDimensionsSize = thisrange.dimensionsSize;
6055 for(size_t k = 0; k < thisrange.dimensionsSize; ++k)
6056 dst->arrayDimensions[k] =
6057 thisrange.dimensions[k].max - thisrange.dimensions[k].min + 1;
6058 }
6059 return UA_STATUSCODE_GOOD;
6060}
6061
6062/* TODO: Allow ranges to reach inside a scalars that are array-like, e.g.
6063 * variant and strings. This is already possible for reading... */
6064static UA_StatusCode
6065Variant_setRange(UA_Variant *v, void *array, size_t arraySize,
6066 const UA_NumericRange range, UA_Boolean copy) {
6067 if(!v->type)
6068 return UA_STATUSCODE_BADINVALIDARGUMENT;
6069
6070 /* Upper bound of the dimensions for stack-allocation */
6071 if(range.dimensionsSize > UA_MAX_ARRAY_DIMS)
6072 return UA_STATUSCODE_BADINTERNALERROR;
6073
6074 /* Copy the const range to a mutable stack location */
6075 UA_NumericRangeDimension thisrangedims[UA_MAX_ARRAY_DIMS];
6076 memcpy(dest: thisrangedims, src: range.dimensions, n: sizeof(UA_NumericRangeDimension) * range.dimensionsSize);
6077 UA_NumericRange thisrange = {range.dimensionsSize, thisrangedims};
6078
6079 UA_StatusCode retval = checkAdjustRange(v, range: &thisrange);
6080 if(retval != UA_STATUSCODE_GOOD)
6081 return retval;
6082
6083 /* Compute the strides */
6084 size_t count, block, stride, first;
6085 computeStrides(v, range, total: &count, block: &block, stride: &stride, first: &first);
6086 if(count != arraySize)
6087 return UA_STATUSCODE_BADINDEXRANGEINVALID;
6088
6089 /* Move/copy the elements */
6090 size_t block_count = count / block;
6091 size_t elem_size = v->type->memSize;
6092 uintptr_t nextdst = (uintptr_t)v->data + (first * elem_size);
6093 uintptr_t nextsrc = (uintptr_t)array;
6094 if(v->type->pointerFree || !copy) {
6095 for(size_t i = 0; i < block_count; ++i) {
6096 memcpy(dest: (void*)nextdst, src: (void*)nextsrc, n: elem_size * block);
6097 nextsrc += block * elem_size;
6098 nextdst += stride * elem_size;
6099 }
6100 } else {
6101 for(size_t i = 0; i < block_count; ++i) {
6102 for(size_t j = 0; j < block; ++j) {
6103 clearJumpTable[v->type->typeKind]((void*)nextdst, v->type);
6104 retval |= UA_copy(src: (void*)nextsrc, dst: (void*)nextdst, type: v->type);
6105 nextdst += elem_size;
6106 nextsrc += elem_size;
6107 }
6108 nextdst += (stride - block) * elem_size;
6109 }
6110 }
6111
6112 /* If members were moved, initialize original array to prevent reuse */
6113 if(!copy && !v->type->pointerFree)
6114 memset(s: array, c: 0, n: sizeof(elem_size)*arraySize);
6115
6116 return retval;
6117}
6118
6119UA_StatusCode
6120UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
6121 size_t arraySize, const UA_NumericRange range) {
6122 return Variant_setRange(v, array, arraySize, range, false);
6123}
6124
6125UA_StatusCode
6126UA_Variant_setRangeCopy(UA_Variant *v, const void * UA_RESTRICT array,
6127 size_t arraySize, const UA_NumericRange range) {
6128 return Variant_setRange(v, array: (void*)(uintptr_t)array,
6129 arraySize, range, true);
6130}
6131
6132/* LocalizedText */
6133static void
6134LocalizedText_clear(UA_LocalizedText *p, const UA_DataType *_) {
6135 String_clear(s: &p->locale, NULL);
6136 String_clear(s: &p->text, NULL);
6137}
6138
6139static UA_StatusCode
6140LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst,
6141 const UA_DataType *_) {
6142 UA_StatusCode retval = String_copy(src: &src->locale, dst: &dst->locale, NULL);
6143 retval |= String_copy(src: &src->text, dst: &dst->text, NULL);
6144 return retval;
6145}
6146
6147/* DataValue */
6148static void
6149DataValue_clear(UA_DataValue *p, const UA_DataType *_) {
6150 Variant_clear(p: &p->value, NULL);
6151}
6152
6153static UA_StatusCode
6154DataValue_copy(UA_DataValue const *src, UA_DataValue *dst,
6155 const UA_DataType *_) {
6156 memcpy(dest: dst, src: src, n: sizeof(UA_DataValue));
6157 UA_Variant_init(p: &dst->value);
6158 UA_StatusCode retval = Variant_copy(src: &src->value, dst: &dst->value, NULL);
6159 if(retval != UA_STATUSCODE_GOOD)
6160 DataValue_clear(p: dst, NULL);
6161 return retval;
6162}
6163
6164UA_StatusCode
6165UA_DataValue_copyVariantRange(const UA_DataValue *src, UA_DataValue * UA_RESTRICT dst,
6166 const UA_NumericRange range) {
6167 memcpy(dest: dst, src: src, n: sizeof(UA_DataValue));
6168 UA_Variant_init(p: &dst->value);
6169 UA_StatusCode retval = UA_Variant_copyRange(src: &src->value, dst: &dst->value, range);
6170 if(retval != UA_STATUSCODE_GOOD)
6171 DataValue_clear(p: dst, NULL);
6172 return retval;
6173}
6174
6175/* DiagnosticInfo */
6176static void
6177DiagnosticInfo_clear(UA_DiagnosticInfo *p, const UA_DataType *_) {
6178 String_clear(s: &p->additionalInfo, NULL);
6179 if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) {
6180 DiagnosticInfo_clear(p: p->innerDiagnosticInfo, NULL);
6181 UA_free(ptr: p->innerDiagnosticInfo);
6182 }
6183}
6184
6185static UA_StatusCode
6186DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst,
6187 const UA_DataType *_) {
6188 memcpy(dest: dst, src: src, n: sizeof(UA_DiagnosticInfo));
6189 UA_String_init(p: &dst->additionalInfo);
6190 dst->innerDiagnosticInfo = NULL;
6191 UA_StatusCode retval = UA_STATUSCODE_GOOD;
6192 if(src->hasAdditionalInfo)
6193 retval = String_copy(src: &src->additionalInfo, dst: &dst->additionalInfo, NULL);
6194 if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) {
6195 dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)
6196 UA_malloc(size: sizeof(UA_DiagnosticInfo));
6197 if(UA_LIKELY(dst->innerDiagnosticInfo != NULL)) {
6198 retval |= DiagnosticInfo_copy(src: src->innerDiagnosticInfo,
6199 dst: dst->innerDiagnosticInfo, NULL);
6200 dst->hasInnerDiagnosticInfo = true;
6201 } else {
6202 dst->hasInnerDiagnosticInfo = false;
6203 retval |= UA_STATUSCODE_BADOUTOFMEMORY;
6204 }
6205 }
6206 return retval;
6207}
6208
6209/********************/
6210/* Structured Types */
6211/********************/
6212
6213void *
6214UA_new(const UA_DataType *type) {
6215 void *p = UA_calloc(nmemb: 1, size: type->memSize);
6216 return p;
6217}
6218
6219static UA_StatusCode
6220copyByte(const u8 *src, u8 *dst, const UA_DataType *_) {
6221 *dst = *src;
6222 return UA_STATUSCODE_GOOD;
6223}
6224
6225static UA_StatusCode
6226copy2Byte(const u16 *src, u16 *dst, const UA_DataType *_) {
6227 *dst = *src;
6228 return UA_STATUSCODE_GOOD;
6229}
6230
6231static UA_StatusCode
6232copy4Byte(const u32 *src, u32 *dst, const UA_DataType *_) {
6233 *dst = *src;
6234 return UA_STATUSCODE_GOOD;
6235}
6236
6237static UA_StatusCode
6238copy8Byte(const u64 *src, u64 *dst, const UA_DataType *_) {
6239 *dst = *src;
6240 return UA_STATUSCODE_GOOD;
6241}
6242
6243static UA_StatusCode
6244copyGuid(const UA_Guid *src, UA_Guid *dst, const UA_DataType *_) {
6245 *dst = *src;
6246 return UA_STATUSCODE_GOOD;
6247}
6248
6249static UA_StatusCode
6250copyStructure(const void *src, void *dst, const UA_DataType *type) {
6251 UA_StatusCode retval = UA_STATUSCODE_GOOD;
6252 uintptr_t ptrs = (uintptr_t)src;
6253 uintptr_t ptrd = (uintptr_t)dst;
6254 for(size_t i = 0; i < type->membersSize; ++i) {
6255 const UA_DataTypeMember *m = &type->members[i];
6256 const UA_DataType *mt = m->memberType;
6257 ptrs += m->padding;
6258 ptrd += m->padding;
6259 if(!m->isOptional) {
6260 if(!m->isArray) {
6261 retval |= copyJumpTable[mt->typeKind]((const void *)ptrs, (void *)ptrd, mt);
6262 ptrs += mt->memSize;
6263 ptrd += mt->memSize;
6264 } else {
6265 size_t *dst_size = (size_t*)ptrd;
6266 const size_t size = *((const size_t*)ptrs);
6267 ptrs += sizeof(size_t);
6268 ptrd += sizeof(size_t);
6269 retval |= UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt);
6270 if(retval == UA_STATUSCODE_GOOD)
6271 *dst_size = size;
6272 else
6273 *dst_size = 0;
6274 ptrs += sizeof(void*);
6275 ptrd += sizeof(void*);
6276 }
6277 } else {
6278 if(!m->isArray) {
6279 if(*(void* const*)ptrs != NULL)
6280 retval |= UA_Array_copy(src: *(void* const*)ptrs, size: 1, dst: (void**)ptrd, type: mt);
6281 } else {
6282 if(*(void* const*)(ptrs+sizeof(size_t)) != NULL) {
6283 size_t *dst_size = (size_t*)ptrd;
6284 const size_t size = *((const size_t*)ptrs);
6285 ptrs += sizeof(size_t);
6286 ptrd += sizeof(size_t);
6287 retval |= UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt);
6288 if(retval == UA_STATUSCODE_GOOD)
6289 *dst_size = size;
6290 else
6291 *dst_size = 0;
6292 } else {
6293 ptrs += sizeof(size_t);
6294 ptrd += sizeof(size_t);
6295 }
6296 }
6297 ptrs += sizeof(void*);
6298 ptrd += sizeof(void*);
6299 }
6300 }
6301 return retval;
6302}
6303
6304static UA_StatusCode
6305copyUnion(const void *src, void *dst, const UA_DataType *type) {
6306 uintptr_t ptrs = (uintptr_t) src;
6307 uintptr_t ptrd = (uintptr_t) dst;
6308 UA_UInt32 selection = *(UA_UInt32 *)ptrs;
6309 UA_copy(src: (const UA_UInt32 *) ptrs, dst: (UA_UInt32 *) ptrd, type: &UA_TYPES[UA_TYPES_UINT32]);
6310 if(selection == 0)
6311 return UA_STATUSCODE_GOOD;
6312 const UA_DataTypeMember *m = &type->members[selection-1];
6313 const UA_DataType *mt = m->memberType;
6314 ptrs += m->padding;
6315 ptrd += m->padding;
6316
6317 UA_StatusCode retval = UA_STATUSCODE_GOOD;
6318
6319 if (m->isArray) {
6320 size_t *dst_size = (size_t*)ptrd;
6321 const size_t size = *((const size_t*)ptrs);
6322 ptrs += sizeof(size_t);
6323 ptrd += sizeof(size_t);
6324 retval = UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt);
6325 if(retval == UA_STATUSCODE_GOOD)
6326 *dst_size = size;
6327 else
6328 *dst_size = 0;
6329 } else {
6330 retval = copyJumpTable[mt->typeKind]((const void *)ptrs, (void *)ptrd, mt);
6331 }
6332
6333 return retval;
6334}
6335
6336static UA_StatusCode
6337copyNotImplemented(const void *src, void *dst, const UA_DataType *type) {
6338 return UA_STATUSCODE_BADNOTIMPLEMENTED;
6339}
6340
6341const UA_copySignature copyJumpTable[UA_DATATYPEKINDS] = {
6342 (UA_copySignature)copyByte, /* Boolean */
6343 (UA_copySignature)copyByte, /* SByte */
6344 (UA_copySignature)copyByte, /* Byte */
6345 (UA_copySignature)copy2Byte, /* Int16 */
6346 (UA_copySignature)copy2Byte, /* UInt16 */
6347 (UA_copySignature)copy4Byte, /* Int32 */
6348 (UA_copySignature)copy4Byte, /* UInt32 */
6349 (UA_copySignature)copy8Byte, /* Int64 */
6350 (UA_copySignature)copy8Byte, /* UInt64 */
6351 (UA_copySignature)copy4Byte, /* Float */
6352 (UA_copySignature)copy8Byte, /* Double */
6353 (UA_copySignature)String_copy,
6354 (UA_copySignature)copy8Byte, /* DateTime */
6355 (UA_copySignature)copyGuid, /* Guid */
6356 (UA_copySignature)String_copy, /* ByteString */
6357 (UA_copySignature)String_copy, /* XmlElement */
6358 (UA_copySignature)NodeId_copy,
6359 (UA_copySignature)ExpandedNodeId_copy,
6360 (UA_copySignature)copy4Byte, /* StatusCode */
6361 (UA_copySignature)QualifiedName_copy,
6362 (UA_copySignature)LocalizedText_copy,
6363 (UA_copySignature)ExtensionObject_copy,
6364 (UA_copySignature)DataValue_copy,
6365 (UA_copySignature)Variant_copy,
6366 (UA_copySignature)DiagnosticInfo_copy,
6367 (UA_copySignature)copyNotImplemented, /* Decimal */
6368 (UA_copySignature)copy4Byte, /* Enumeration */
6369 (UA_copySignature)copyStructure,
6370 (UA_copySignature)copyStructure, /* Structure with Optional Fields */
6371 (UA_copySignature)copyUnion, /* Union */
6372 (UA_copySignature)copyNotImplemented /* BitfieldCluster*/
6373};
6374
6375UA_StatusCode
6376UA_copy(const void *src, void *dst, const UA_DataType *type) {
6377 memset(s: dst, c: 0, n: type->memSize); /* init */
6378 UA_StatusCode retval = copyJumpTable[type->typeKind](src, dst, type);
6379 if(retval != UA_STATUSCODE_GOOD)
6380 UA_clear(p: dst, type);
6381 return retval;
6382}
6383
6384static void
6385clearStructure(void *p, const UA_DataType *type) {
6386 uintptr_t ptr = (uintptr_t)p;
6387 for(size_t i = 0; i < type->membersSize; ++i) {
6388 const UA_DataTypeMember *m = &type->members[i];
6389 const UA_DataType *mt = m->memberType;
6390 ptr += m->padding;
6391 if(!m->isOptional) {
6392 if(!m->isArray) {
6393 clearJumpTable[mt->typeKind]((void*)ptr, mt);
6394 ptr += mt->memSize;
6395 } else {
6396 size_t length = *(size_t*)ptr;
6397 ptr += sizeof(size_t);
6398 UA_Array_delete(p: *(void**)ptr, size: length, type: mt);
6399 ptr += sizeof(void*);
6400 }
6401 } else { /* field is optional */
6402 if(!m->isArray) {
6403 /* optional scalar field is contained */
6404 if((*(void *const *)ptr != NULL))
6405 UA_Array_delete(p: *(void **)ptr, size: 1, type: mt);
6406 ptr += sizeof(void *);
6407 } else {
6408 /* optional array field is contained */
6409 if((*(void *const *)(ptr + sizeof(size_t)) != NULL)) {
6410 size_t length = *(size_t *)ptr;
6411 ptr += sizeof(size_t);
6412 UA_Array_delete(p: *(void **)ptr, size: length, type: mt);
6413 ptr += sizeof(void *);
6414 } else { /* optional array field not contained */
6415 ptr += sizeof(size_t);
6416 ptr += sizeof(void *);
6417 }
6418 }
6419 }
6420 }
6421}
6422
6423static void
6424clearUnion(void *p, const UA_DataType *type) {
6425 uintptr_t ptr = (uintptr_t) p;
6426 UA_UInt32 selection = *(UA_UInt32 *)ptr;
6427 if(selection == 0)
6428 return;
6429 const UA_DataTypeMember *m = &type->members[selection-1];
6430 const UA_DataType *mt = m->memberType;
6431 ptr += m->padding;
6432 if (m->isArray) {
6433 size_t length = *(size_t *)ptr;
6434 ptr += sizeof(size_t);
6435 UA_Array_delete(p: *(void **)ptr, size: length, type: mt);
6436 } else {
6437 UA_clear(p: (void *) ptr, type: mt);
6438 }
6439}
6440
6441static void nopClear(void *p, const UA_DataType *type) { }
6442
6443const
6444UA_clearSignature clearJumpTable[UA_DATATYPEKINDS] = {
6445 (UA_clearSignature)nopClear, /* Boolean */
6446 (UA_clearSignature)nopClear, /* SByte */
6447 (UA_clearSignature)nopClear, /* Byte */
6448 (UA_clearSignature)nopClear, /* Int16 */
6449 (UA_clearSignature)nopClear, /* UInt16 */
6450 (UA_clearSignature)nopClear, /* Int32 */
6451 (UA_clearSignature)nopClear, /* UInt32 */
6452 (UA_clearSignature)nopClear, /* Int64 */
6453 (UA_clearSignature)nopClear, /* UInt64 */
6454 (UA_clearSignature)nopClear, /* Float */
6455 (UA_clearSignature)nopClear, /* Double */
6456 (UA_clearSignature)String_clear, /* String */
6457 (UA_clearSignature)nopClear, /* DateTime */
6458 (UA_clearSignature)nopClear, /* Guid */
6459 (UA_clearSignature)String_clear, /* ByteString */
6460 (UA_clearSignature)String_clear, /* XmlElement */
6461 (UA_clearSignature)NodeId_clear,
6462 (UA_clearSignature)ExpandedNodeId_clear,
6463 (UA_clearSignature)nopClear, /* StatusCode */
6464 (UA_clearSignature)QualifiedName_clear,
6465 (UA_clearSignature)LocalizedText_clear,
6466 (UA_clearSignature)ExtensionObject_clear,
6467 (UA_clearSignature)DataValue_clear,
6468 (UA_clearSignature)Variant_clear,
6469 (UA_clearSignature)DiagnosticInfo_clear,
6470 (UA_clearSignature)nopClear, /* Decimal, not implemented */
6471 (UA_clearSignature)nopClear, /* Enumeration */
6472 (UA_clearSignature)clearStructure,
6473 (UA_clearSignature)clearStructure, /* Struct with Optional Fields*/
6474 (UA_clearSignature)clearUnion, /* Union*/
6475 (UA_clearSignature)nopClear /* BitfieldCluster, not implemented*/
6476};
6477
6478void
6479UA_clear(void *p, const UA_DataType *type) {
6480 clearJumpTable[type->typeKind](p, type);
6481 memset(s: p, c: 0, n: type->memSize); /* init */
6482}
6483
6484void
6485UA_delete(void *p, const UA_DataType *type) {
6486 clearJumpTable[type->typeKind](p, type);
6487 UA_free(ptr: p);
6488}
6489
6490/******************/
6491/* Value Ordering */
6492/******************/
6493
6494#define UA_NUMERICORDER(NAME, TYPE) \
6495 static UA_Order \
6496 NAME(const TYPE *p1, const TYPE *p2, const UA_DataType *type) { \
6497 if(*p1 != *p2) \
6498 return (*p1 < *p2) ? UA_ORDER_LESS : UA_ORDER_MORE; \
6499 return UA_ORDER_EQ; \
6500 }
6501
6502UA_NUMERICORDER(booleanOrder, UA_Boolean)
6503UA_NUMERICORDER(sByteOrder, UA_SByte)
6504UA_NUMERICORDER(byteOrder, UA_Byte)
6505UA_NUMERICORDER(int16Order, UA_Int16)
6506UA_NUMERICORDER(uInt16Order, UA_UInt16)
6507UA_NUMERICORDER(int32Order, UA_Int32)
6508UA_NUMERICORDER(uInt32Order, UA_UInt32)
6509UA_NUMERICORDER(int64Order, UA_Int64)
6510UA_NUMERICORDER(uInt64Order, UA_UInt64)
6511
6512#define UA_FLOATORDER(NAME, TYPE) \
6513 static UA_Order \
6514 NAME(const TYPE *p1, const TYPE *p2, const UA_DataType *type) { \
6515 if(*p1 != *p2) { \
6516 /* p1 is NaN */ \
6517 if(*p1 != *p1) { \
6518 if(*p2 != *p2) \
6519 return UA_ORDER_EQ; \
6520 return UA_ORDER_LESS; \
6521 } \
6522 /* p2 is NaN */ \
6523 if(*p2 != *p2) \
6524 return UA_ORDER_MORE; \
6525 return (*p1 < *p2) ? UA_ORDER_LESS : UA_ORDER_MORE; \
6526 } \
6527 return UA_ORDER_EQ; \
6528 }
6529
6530UA_FLOATORDER(floatOrder, UA_Float)
6531UA_FLOATORDER(doubleOrder, UA_Double)
6532
6533static UA_Order
6534guidOrder(const UA_Guid *p1, const UA_Guid *p2, const UA_DataType *type) {
6535 if(p1->data1 != p2->data1)
6536 return (p1->data1 < p2->data1) ? UA_ORDER_LESS : UA_ORDER_MORE;
6537 if(p1->data2 != p2->data2)
6538 return (p1->data2 < p2->data2) ? UA_ORDER_LESS : UA_ORDER_MORE;
6539 if(p1->data3 != p2->data3)
6540 return (p1->data3 < p2->data3) ? UA_ORDER_LESS : UA_ORDER_MORE;
6541 int cmp = memcmp(s1: p1->data4, s2: p2->data4, n: 8);
6542 if(cmp != 0)
6543 return (cmp < 0) ? UA_ORDER_LESS : UA_ORDER_MORE;
6544 return UA_ORDER_EQ;
6545}
6546
6547static UA_Order
6548stringOrder(const UA_String *p1, const UA_String *p2, const UA_DataType *type) {
6549 if(p1->length != p2->length)
6550 return (p1->length < p2->length) ? UA_ORDER_LESS : UA_ORDER_MORE;
6551 /* For zero-length arrays, every pointer not NULL is considered a
6552 * UA_EMPTY_ARRAY_SENTINEL. */
6553 if(p1->data == p2->data) return UA_ORDER_EQ;
6554 if(p1->data == NULL) return UA_ORDER_LESS;
6555 if(p2->data == NULL) return UA_ORDER_MORE;
6556 int cmp = memcmp(s1: (const char*)p1->data, s2: (const char*)p2->data, n: p1->length);
6557 if(cmp != 0)
6558 return (cmp < 0) ? UA_ORDER_LESS : UA_ORDER_MORE;
6559 return UA_ORDER_EQ;
6560}
6561
6562static UA_Order
6563nodeIdOrder(const UA_NodeId *p1, const UA_NodeId *p2, const UA_DataType *type) {
6564 return UA_NodeId_order(n1: p1, n2: p2);
6565}
6566
6567static UA_Order
6568expandedNodeIdOrder(const UA_ExpandedNodeId *p1, const UA_ExpandedNodeId *p2,
6569 const UA_DataType *type) {
6570 return UA_ExpandedNodeId_order(n1: p1, n2: p2);
6571}
6572
6573static UA_Order
6574qualifiedNameOrder(const UA_QualifiedName *p1, const UA_QualifiedName *p2,
6575 const UA_DataType *type) {
6576 if(p1->namespaceIndex != p2->namespaceIndex)
6577 return (p1->namespaceIndex < p2->namespaceIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
6578 return stringOrder(p1: &p1->name, p2: &p2->name, NULL);
6579}
6580
6581static UA_Order
6582localizedTextOrder(const UA_LocalizedText *p1, const UA_LocalizedText *p2,
6583 const UA_DataType *type) {
6584 UA_Order o = stringOrder(p1: &p1->locale, p2: &p2->locale, NULL);
6585 if(o != UA_ORDER_EQ)
6586 return o;
6587 return stringOrder(p1: &p1->text, p2: &p2->text, NULL);
6588}
6589
6590static UA_Order
6591extensionObjectOrder(const UA_ExtensionObject *p1, const UA_ExtensionObject *p2,
6592 const UA_DataType *type) {
6593 UA_ExtensionObjectEncoding enc1 = p1->encoding;
6594 UA_ExtensionObjectEncoding enc2 = p2->encoding;
6595 if(enc1 > UA_EXTENSIONOBJECT_DECODED)
6596 enc1 = UA_EXTENSIONOBJECT_DECODED;
6597 if(enc2 > UA_EXTENSIONOBJECT_DECODED)
6598 enc2 = UA_EXTENSIONOBJECT_DECODED;
6599 if(enc1 != enc2)
6600 return (enc1 < enc2) ? UA_ORDER_LESS : UA_ORDER_MORE;
6601
6602 switch(enc1) {
6603 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
6604 return UA_ORDER_EQ;
6605
6606 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
6607 case UA_EXTENSIONOBJECT_ENCODED_XML: {
6608 UA_Order o = UA_NodeId_order(n1: &p1->content.encoded.typeId,
6609 n2: &p2->content.encoded.typeId);
6610 if(o == UA_ORDER_EQ)
6611 o = stringOrder(p1: (const UA_String*)&p1->content.encoded.body,
6612 p2: (const UA_String*)&p2->content.encoded.body, NULL);
6613 return o;
6614 }
6615
6616 case UA_EXTENSIONOBJECT_DECODED:
6617 default: {
6618 const UA_DataType *type1 = p1->content.decoded.type;
6619 const UA_DataType *type2 = p1->content.decoded.type;
6620 if(type1 != type2)
6621 return ((uintptr_t)type1 < (uintptr_t)type2) ? UA_ORDER_LESS : UA_ORDER_MORE;
6622 if(!type1)
6623 return UA_ORDER_EQ;
6624 return orderJumpTable[type1->typeKind]
6625 (p1->content.decoded.data, p2->content.decoded.data, type1);
6626 }
6627 }
6628}
6629
6630static UA_Order
6631arrayOrder(const void *p1, size_t p1Length, const void *p2, size_t p2Length,
6632 const UA_DataType *type) {
6633 if(p1Length != p2Length)
6634 return (p1Length < p2Length) ? UA_ORDER_LESS : UA_ORDER_MORE;
6635 /* For zero-length arrays, every pointer not NULL is considered a
6636 * UA_EMPTY_ARRAY_SENTINEL. */
6637 if(p1 == p2) return UA_ORDER_EQ;
6638 if(p1 == NULL) return UA_ORDER_LESS;
6639 if(p2 == NULL) return UA_ORDER_MORE;
6640 uintptr_t u1 = (uintptr_t)p1;
6641 uintptr_t u2 = (uintptr_t)p2;
6642 for(size_t i = 0; i < p1Length; i++) {
6643 UA_Order o = orderJumpTable[type->typeKind]((const void*)u1, (const void*)u2, type);
6644 if(o != UA_ORDER_EQ)
6645 return o;
6646 u1 += type->memSize;
6647 u2 += type->memSize;
6648 }
6649 return UA_ORDER_EQ;
6650}
6651
6652static UA_Order
6653variantOrder(const UA_Variant *p1, const UA_Variant *p2,
6654 const UA_DataType *type) {
6655 if(p1->type != p2->type)
6656 return ((uintptr_t)p1->type < (uintptr_t)p2->type) ? UA_ORDER_LESS : UA_ORDER_MORE;
6657
6658 UA_Order o;
6659 if(p1->type != NULL) {
6660 /* Check if both variants are scalars or arrays */
6661 UA_Boolean s1 = UA_Variant_isScalar(v: p1);
6662 UA_Boolean s2 = UA_Variant_isScalar(v: p2);
6663 if(s1 != s2)
6664 return s1 ? UA_ORDER_LESS : UA_ORDER_MORE;
6665 if(s1) {
6666 o = orderJumpTable[p1->type->typeKind](p1->data, p2->data, p1->type);
6667 } else {
6668 /* Mismatching array length? */
6669 if(p1->arrayLength != p2->arrayLength)
6670 return (p1->arrayLength < p2->arrayLength) ? UA_ORDER_LESS : UA_ORDER_MORE;
6671 o = arrayOrder(p1: p1->data, p1Length: p1->arrayLength, p2: p2->data, p2Length: p2->arrayLength, type: p1->type);
6672 }
6673 if(o != UA_ORDER_EQ)
6674 return o;
6675 }
6676
6677 if(p1->arrayDimensionsSize != p2->arrayDimensionsSize)
6678 return (p1->arrayDimensionsSize < p2->arrayDimensionsSize) ?
6679 UA_ORDER_LESS : UA_ORDER_MORE;
6680 o = UA_ORDER_EQ;
6681 if(p1->arrayDimensionsSize > 0)
6682 o = arrayOrder(p1: p1->arrayDimensions, p1Length: p1->arrayDimensionsSize,
6683 p2: p2->arrayDimensions, p2Length: p2->arrayDimensionsSize,
6684 type: &UA_TYPES[UA_TYPES_UINT32]);
6685 return o;
6686}
6687
6688static UA_Order
6689dataValueOrder(const UA_DataValue *p1, const UA_DataValue *p2,
6690 const UA_DataType *type) {
6691 /* Value */
6692 if(p1->hasValue != p2->hasValue)
6693 return (!p1->hasValue) ? UA_ORDER_LESS : UA_ORDER_MORE;
6694 if(p1->hasValue) {
6695 UA_Order o = variantOrder(p1: &p1->value, p2: &p2->value, NULL);
6696 if(o != UA_ORDER_EQ)
6697 return o;
6698 }
6699
6700 /* Status */
6701 if(p1->hasStatus != p2->hasStatus)
6702 return (!p1->hasStatus) ? UA_ORDER_LESS : UA_ORDER_MORE;
6703 if(p1->hasStatus && p1->status != p2->status)
6704 return (p1->status < p2->status) ? UA_ORDER_LESS : UA_ORDER_MORE;
6705
6706 /* SourceTimestamp */
6707 if(p1->hasSourceTimestamp != p2->hasSourceTimestamp)
6708 return (!p1->hasSourceTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
6709 if(p1->hasSourceTimestamp && p1->sourceTimestamp != p2->sourceTimestamp)
6710 return (p1->sourceTimestamp < p2->sourceTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
6711
6712 /* ServerTimestamp */
6713 if(p1->hasServerTimestamp != p2->hasServerTimestamp)
6714 return (!p1->hasServerTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
6715 if(p1->hasServerTimestamp && p1->serverTimestamp != p2->serverTimestamp)
6716 return (p1->serverTimestamp < p2->serverTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
6717
6718 /* SourcePicoseconds */
6719 if(p1->hasSourcePicoseconds != p2->hasSourcePicoseconds)
6720 return (!p1->hasSourcePicoseconds) ? UA_ORDER_LESS : UA_ORDER_MORE;
6721 if(p1->hasSourcePicoseconds && p1->sourcePicoseconds != p2->sourcePicoseconds)
6722 return (p1->sourcePicoseconds < p2->sourcePicoseconds) ?
6723 UA_ORDER_LESS : UA_ORDER_MORE;
6724
6725 /* ServerPicoseconds */
6726 if(p1->hasServerPicoseconds != p2->hasServerPicoseconds)
6727 return (!p1->hasServerPicoseconds) ? UA_ORDER_LESS : UA_ORDER_MORE;
6728 if(p1->hasServerPicoseconds && p1->serverPicoseconds != p2->serverPicoseconds)
6729 return (p1->serverPicoseconds < p2->serverPicoseconds) ?
6730 UA_ORDER_LESS : UA_ORDER_MORE;
6731
6732 return UA_ORDER_EQ;
6733}
6734
6735static UA_Order
6736diagnosticInfoOrder(const UA_DiagnosticInfo *p1, const UA_DiagnosticInfo *p2,
6737 const UA_DataType *type) {
6738 /* SymbolicId */
6739 if(p1->hasSymbolicId != p2->hasSymbolicId)
6740 return (!p1->hasSymbolicId) ? UA_ORDER_LESS : UA_ORDER_MORE;
6741 if(p1->hasSymbolicId && p1->symbolicId != p2->symbolicId)
6742 return (p1->symbolicId < p2->symbolicId) ? UA_ORDER_LESS : UA_ORDER_MORE;
6743
6744 /* NamespaceUri */
6745 if(p1->hasNamespaceUri != p2->hasNamespaceUri)
6746 return (!p1->hasNamespaceUri) ? UA_ORDER_LESS : UA_ORDER_MORE;
6747 if(p1->hasNamespaceUri && p1->namespaceUri != p2->namespaceUri)
6748 return (p1->namespaceUri < p2->namespaceUri) ? UA_ORDER_LESS : UA_ORDER_MORE;
6749
6750 /* LocalizedText */
6751 if(p1->hasLocalizedText != p2->hasLocalizedText)
6752 return (!p1->hasLocalizedText) ? UA_ORDER_LESS : UA_ORDER_MORE;
6753 if(p1->hasLocalizedText && p1->localizedText != p2->localizedText)
6754 return (p1->localizedText < p2->localizedText) ? UA_ORDER_LESS : UA_ORDER_MORE;
6755
6756 /* Locale */
6757 if(p1->hasLocale != p2->hasLocale)
6758 return (!p1->hasLocale) ? UA_ORDER_LESS : UA_ORDER_MORE;
6759 if(p1->hasLocale && p1->locale != p2->locale)
6760 return (p1->locale < p2->locale) ? UA_ORDER_LESS : UA_ORDER_MORE;
6761
6762 /* AdditionalInfo */
6763 if(p1->hasAdditionalInfo != p2->hasAdditionalInfo)
6764 return (!p1->hasAdditionalInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
6765 if(p1->hasAdditionalInfo) {
6766 UA_Order o = stringOrder(p1: &p1->additionalInfo, p2: &p2->additionalInfo, NULL);
6767 if(o != UA_ORDER_EQ)
6768 return o;
6769 }
6770
6771 /* InnerStatusCode */
6772 if(p1->hasInnerStatusCode != p2->hasInnerStatusCode)
6773 return (!p1->hasInnerStatusCode) ? UA_ORDER_LESS : UA_ORDER_MORE;
6774 if(p1->hasInnerStatusCode && p1->innerStatusCode != p2->innerStatusCode)
6775 return (p1->innerStatusCode < p2->innerStatusCode) ? UA_ORDER_LESS : UA_ORDER_MORE;
6776
6777 /* InnerDiagnosticInfo */
6778 if(p1->hasInnerDiagnosticInfo != p2->hasInnerDiagnosticInfo)
6779 return (!p1->hasInnerDiagnosticInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
6780 if(p1->innerDiagnosticInfo == p2->innerDiagnosticInfo)
6781 return UA_ORDER_EQ;
6782 if(!p1->innerDiagnosticInfo || !p2->innerDiagnosticInfo)
6783 return (!p1->innerDiagnosticInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
6784 return diagnosticInfoOrder(p1: p1->innerDiagnosticInfo, p2: p2->innerDiagnosticInfo, NULL);
6785}
6786
6787static UA_Order
6788structureOrder(const void *p1, const void *p2, const UA_DataType *type) {
6789 uintptr_t u1 = (uintptr_t)p1;
6790 uintptr_t u2 = (uintptr_t)p2;
6791 UA_Order o = UA_ORDER_EQ;
6792 for(size_t i = 0; i < type->membersSize; ++i) {
6793 const UA_DataTypeMember *m = &type->members[i];
6794 const UA_DataType *mt = m->memberType;
6795 u1 += m->padding;
6796 u2 += m->padding;
6797 if(!m->isOptional) {
6798 if(!m->isArray) {
6799 o = orderJumpTable[mt->typeKind]((const void *)u1, (const void *)u2, mt);
6800 u1 += mt->memSize;
6801 u2 += mt->memSize;
6802 } else {
6803 size_t size1 = *(size_t*)u1;
6804 size_t size2 = *(size_t*)u2;
6805 u1 += sizeof(size_t);
6806 u2 += sizeof(size_t);
6807 o = arrayOrder(p1: *(void* const*)u1, p1Length: size1, p2: *(void* const*)u2, p2Length: size2, type: mt);
6808 u1 += sizeof(void*);
6809 u2 += sizeof(void*);
6810 }
6811 } else {
6812 if(!m->isArray) {
6813 const void *pp1 = *(void* const*)u1;
6814 const void *pp2 = *(void* const*)u2;
6815 if(pp1 == pp2) {
6816 o = UA_ORDER_EQ;
6817 } else if(pp1 == NULL) {
6818 o = UA_ORDER_LESS;
6819 } else if(pp2 == NULL) {
6820 o = UA_ORDER_MORE;
6821 } else {
6822 o = orderJumpTable[mt->typeKind](pp1, pp2, mt);
6823 }
6824 } else {
6825 size_t sa1 = *(size_t*)u1;
6826 size_t sa2 = *(size_t*)u2;
6827 u1 += sizeof(size_t);
6828 u2 += sizeof(size_t);
6829 o = arrayOrder(p1: *(void* const*)u1, p1Length: sa1, p2: *(void* const*)u2, p2Length: sa2, type: mt);
6830 }
6831 u1 += sizeof(void*);
6832 u2 += sizeof(void*);
6833 }
6834
6835 if(o != UA_ORDER_EQ)
6836 break;
6837 }
6838 return o;
6839}
6840
6841static UA_Order
6842unionOrder(const void *p1, const void *p2, const UA_DataType *type) {
6843 UA_UInt32 sel1 = *(const UA_UInt32 *)p1;
6844 UA_UInt32 sel2 = *(const UA_UInt32 *)p2;
6845 if(sel1 != sel2)
6846 return (sel1 < sel2) ? UA_ORDER_LESS : UA_ORDER_MORE;
6847
6848 if(sel1 == 0) {
6849 return UA_ORDER_EQ;
6850 }
6851
6852 const UA_DataTypeMember *m = &type->members[sel1-1];
6853 const UA_DataType *mt = m->memberType;
6854
6855 uintptr_t u1 = ((uintptr_t)p1) + m->padding; /* includes switchfield length */
6856 uintptr_t u2 = ((uintptr_t)p2) + m->padding;
6857 if(m->isArray) {
6858 size_t sa1 = *(size_t*)u1;
6859 size_t sa2 = *(size_t*)u2;
6860 u1 += sizeof(size_t);
6861 u2 += sizeof(size_t);
6862 return arrayOrder(p1: *(void* const*)u1, p1Length: sa1, p2: *(void* const*)u2, p2Length: sa2, type: mt);
6863 }
6864 return orderJumpTable[mt->typeKind]((const void*)u1, (const void*)u2, mt);
6865}
6866
6867static UA_Order
6868notImplementedOrder(const void *p1, const void *p2, const UA_DataType *type) {
6869 return UA_ORDER_EQ;
6870}
6871
6872const
6873UA_orderSignature orderJumpTable[UA_DATATYPEKINDS] = {
6874 (UA_orderSignature)booleanOrder,
6875 (UA_orderSignature)sByteOrder,
6876 (UA_orderSignature)byteOrder,
6877 (UA_orderSignature)int16Order,
6878 (UA_orderSignature)uInt16Order,
6879 (UA_orderSignature)int32Order,
6880 (UA_orderSignature)uInt32Order,
6881 (UA_orderSignature)int64Order,
6882 (UA_orderSignature)uInt64Order,
6883 (UA_orderSignature)floatOrder,
6884 (UA_orderSignature)doubleOrder,
6885 (UA_orderSignature)stringOrder,
6886 (UA_orderSignature)int64Order, /* DateTime */
6887 (UA_orderSignature)guidOrder,
6888 (UA_orderSignature)stringOrder, /* ByteString */
6889 (UA_orderSignature)stringOrder, /* XmlElement */
6890 (UA_orderSignature)nodeIdOrder,
6891 (UA_orderSignature)expandedNodeIdOrder,
6892 (UA_orderSignature)uInt32Order, /* StatusCode */
6893 (UA_orderSignature)qualifiedNameOrder,
6894 (UA_orderSignature)localizedTextOrder,
6895 (UA_orderSignature)extensionObjectOrder,
6896 (UA_orderSignature)dataValueOrder,
6897 (UA_orderSignature)variantOrder,
6898 (UA_orderSignature)diagnosticInfoOrder,
6899 notImplementedOrder, /* Decimal, not implemented */
6900 (UA_orderSignature)uInt32Order, /* Enumeration */
6901 (UA_orderSignature)structureOrder,
6902 (UA_orderSignature)structureOrder, /* Struct with Optional Fields*/
6903 (UA_orderSignature)unionOrder, /* Union*/
6904 notImplementedOrder /* BitfieldCluster, not implemented */
6905};
6906
6907UA_Order UA_order(const void *p1, const void *p2, const UA_DataType *type) {
6908 return orderJumpTable[type->typeKind](p1, p2, type);
6909}
6910
6911/******************/
6912/* Array Handling */
6913/******************/
6914
6915void *
6916UA_Array_new(size_t size, const UA_DataType *type) {
6917 if(size > UA_INT32_MAX)
6918 return NULL;
6919 if(size == 0)
6920 return UA_EMPTY_ARRAY_SENTINEL;
6921 return UA_calloc(nmemb: size, size: type->memSize);
6922}
6923
6924UA_StatusCode
6925UA_Array_copy(const void *src, size_t size,
6926 void **dst, const UA_DataType *type) {
6927 if(size == 0) {
6928 if(src == NULL)
6929 *dst = NULL;
6930 else
6931 *dst= UA_EMPTY_ARRAY_SENTINEL;
6932 return UA_STATUSCODE_GOOD;
6933 }
6934
6935 if(!type)
6936 return UA_STATUSCODE_BADINTERNALERROR;
6937
6938 /* calloc, so we don't have to check retval in every iteration of copying */
6939 *dst = UA_calloc(nmemb: size, size: type->memSize);
6940 if(!*dst)
6941 return UA_STATUSCODE_BADOUTOFMEMORY;
6942
6943 if(type->pointerFree) {
6944 memcpy(dest: *dst, src: src, n: type->memSize * size);
6945 return UA_STATUSCODE_GOOD;
6946 }
6947
6948 uintptr_t ptrs = (uintptr_t)src;
6949 uintptr_t ptrd = (uintptr_t)*dst;
6950 UA_StatusCode retval = UA_STATUSCODE_GOOD;
6951 for(size_t i = 0; i < size; ++i) {
6952 retval |= UA_copy(src: (void*)ptrs, dst: (void*)ptrd, type);
6953 ptrs += type->memSize;
6954 ptrd += type->memSize;
6955 }
6956 if(retval != UA_STATUSCODE_GOOD) {
6957 UA_Array_delete(p: *dst, size, type);
6958 *dst = NULL;
6959 }
6960 return retval;
6961}
6962
6963UA_StatusCode
6964UA_Array_resize(void **p, size_t *size, size_t newSize,
6965 const UA_DataType *type) {
6966 if(*size == newSize)
6967 return UA_STATUSCODE_GOOD;
6968
6969 /* Empty array? */
6970 if(newSize == 0) {
6971 UA_Array_delete(p: *p, size: *size, type);
6972 *p = UA_EMPTY_ARRAY_SENTINEL;
6973 *size = 0;
6974 return UA_STATUSCODE_GOOD;
6975 }
6976
6977 /* Make a copy of the members that shall be removed. Realloc can fail during
6978 * trimming. So we cannot clear the members already here. */
6979 void *deleteMembers = NULL;
6980 if(newSize < *size && !type->pointerFree) {
6981 size_t deleteSize = *size - newSize;
6982 deleteMembers = UA_malloc(size: deleteSize * type->memSize);
6983 if(!deleteMembers)
6984 return UA_STATUSCODE_BADOUTOFMEMORY;
6985 memcpy(dest: deleteMembers, src: (void*)((uintptr_t)*p + (newSize * type->memSize)),
6986 n: deleteSize * type->memSize); /* shallow copy */
6987 }
6988
6989 void *oldP = *p;
6990 if(oldP == UA_EMPTY_ARRAY_SENTINEL)
6991 oldP = NULL;
6992
6993 /* Realloc */
6994 void *newP = UA_realloc(ptr: oldP, size: newSize * type->memSize);
6995 if(!newP) {
6996 if(deleteMembers)
6997 UA_free(ptr: deleteMembers);
6998 return UA_STATUSCODE_BADOUTOFMEMORY;
6999 }
7000
7001 /* Clear removed members or initialize the new ones. Note that deleteMembers
7002 * depends on type->pointerFree. */
7003 if(newSize > *size)
7004 memset(s: (void*)((uintptr_t)newP + (*size * type->memSize)), c: 0,
7005 n: (newSize - *size) * type->memSize);
7006 else if(deleteMembers)
7007 UA_Array_delete(p: deleteMembers, size: *size - newSize, type);
7008
7009 /* Set the new array */
7010 *p = newP;
7011 *size = newSize;
7012 return UA_STATUSCODE_GOOD;
7013}
7014
7015UA_StatusCode
7016UA_Array_append(void **p, size_t *size, void *newElem,
7017 const UA_DataType *type) {
7018 /* Resize the array */
7019 size_t oldSize = *size;
7020 UA_StatusCode res = UA_Array_resize(p, size, newSize: oldSize+1, type);
7021 if(res != UA_STATUSCODE_GOOD)
7022 return res;
7023
7024 /* Move the value */
7025 memcpy(dest: (void*)((uintptr_t)*p + (oldSize * type->memSize)),
7026 src: newElem, n: type->memSize);
7027 UA_init(p: newElem, type);
7028 return UA_STATUSCODE_GOOD;
7029}
7030
7031UA_StatusCode UA_EXPORT
7032UA_Array_appendCopy(void **p, size_t *size, const void *newElem,
7033 const UA_DataType *type) {
7034 char scratch[512];
7035 if(type->memSize > 512)
7036 return UA_STATUSCODE_BADINTERNALERROR;
7037
7038 /* Copy the value */
7039 UA_StatusCode res = UA_copy(src: newElem, dst: (void*)scratch, type);
7040 if(res != UA_STATUSCODE_GOOD)
7041 return res;
7042
7043 /* Append */
7044 res = UA_Array_append(p, size, newElem: (void*)scratch, type);
7045 if(res != UA_STATUSCODE_GOOD)
7046 UA_clear(p: (void*)scratch, type);
7047 return res;
7048}
7049
7050void
7051UA_Array_delete(void *p, size_t size, const UA_DataType *type) {
7052 if(!type->pointerFree) {
7053 uintptr_t ptr = (uintptr_t)p;
7054 for(size_t i = 0; i < size; ++i) {
7055 UA_clear(p: (void*)ptr, type);
7056 ptr += type->memSize;
7057 }
7058 }
7059 UA_free(ptr: (void*)((uintptr_t)p & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
7060}
7061
7062#ifdef UA_ENABLE_TYPEDESCRIPTION
7063UA_Boolean
7064UA_DataType_getStructMember(const UA_DataType *type, const char *memberName,
7065 size_t *outOffset, const UA_DataType **outMemberType,
7066 UA_Boolean *outIsArray) {
7067 if(type->typeKind != UA_DATATYPEKIND_STRUCTURE &&
7068 type->typeKind != UA_DATATYPEKIND_OPTSTRUCT)
7069 return false;
7070
7071 size_t offset = 0;
7072 for(size_t i = 0; i < type->membersSize; ++i) {
7073 const UA_DataTypeMember *m = &type->members[i];
7074 const UA_DataType *mt = m->memberType;
7075 offset += m->padding;
7076
7077 if(strcmp(s1: memberName, s2: m->memberName) == 0) {
7078 *outOffset = offset;
7079 *outMemberType = mt;
7080 *outIsArray = m->isArray;
7081 return true;
7082 }
7083
7084 if(!m->isOptional) {
7085 if(!m->isArray) {
7086 offset += mt->memSize;
7087 } else {
7088 offset += sizeof(size_t);
7089 offset += sizeof(void*);
7090 }
7091 } else { /* field is optional */
7092 if(!m->isArray) {
7093 offset += sizeof(void *);
7094 } else {
7095 offset += sizeof(size_t);
7096 offset += sizeof(void *);
7097 }
7098 }
7099 }
7100
7101 return false;
7102}
7103#endif
7104
7105UA_Boolean
7106UA_DataType_isNumeric(const UA_DataType *type) {
7107 switch(type->typeKind) {
7108 case UA_DATATYPEKIND_SBYTE:
7109 case UA_DATATYPEKIND_BYTE:
7110 case UA_DATATYPEKIND_INT16:
7111 case UA_DATATYPEKIND_UINT16:
7112 case UA_DATATYPEKIND_INT32:
7113 case UA_DATATYPEKIND_UINT32:
7114 case UA_DATATYPEKIND_INT64:
7115 case UA_DATATYPEKIND_UINT64:
7116 case UA_DATATYPEKIND_FLOAT:
7117 case UA_DATATYPEKIND_DOUBLE:
7118 /* not implemented: UA_DATATYPEKIND_DECIMAL */
7119 return true;
7120 default:
7121 return false;
7122 }
7123}
7124
7125UA_Int16
7126UA_DataType_getPrecedence(const UA_DataType *type){
7127 //Defined in Part 4 Table 123 "Data Precedence Rules"
7128 switch(type->typeKind) {
7129 case UA_DATATYPEKIND_DOUBLE:
7130 return 1;
7131 case UA_DATATYPEKIND_FLOAT:
7132 return 2;
7133 case UA_DATATYPEKIND_INT64:
7134 return 3;
7135 case UA_DATATYPEKIND_UINT64:
7136 return 4;
7137 case UA_DATATYPEKIND_INT32:
7138 return 5;
7139 case UA_DATATYPEKIND_UINT32:
7140 return 6;
7141 case UA_DATATYPEKIND_STATUSCODE:
7142 return 7;
7143 case UA_DATATYPEKIND_INT16:
7144 return 8;
7145 case UA_DATATYPEKIND_UINT16:
7146 return 9;
7147 case UA_DATATYPEKIND_SBYTE:
7148 return 10;
7149 case UA_DATATYPEKIND_BYTE:
7150 return 11;
7151 case UA_DATATYPEKIND_BOOLEAN:
7152 return 12;
7153 case UA_DATATYPEKIND_GUID:
7154 return 13;
7155 case UA_DATATYPEKIND_STRING:
7156 return 14;
7157 case UA_DATATYPEKIND_EXPANDEDNODEID:
7158 return 15;
7159 case UA_DATATYPEKIND_NODEID:
7160 return 16;
7161 case UA_DATATYPEKIND_LOCALIZEDTEXT:
7162 return 17;
7163 case UA_DATATYPEKIND_QUALIFIEDNAME:
7164 return 18;
7165 default:
7166 return -1;
7167 }
7168}
7169
7170/**********************/
7171/* Parse NumericRange */
7172/**********************/
7173
7174static size_t
7175readDimension(UA_Byte *buf, size_t buflen, UA_NumericRangeDimension *dim) {
7176 size_t progress = UA_readNumber(buf, buflen, number: &dim->min);
7177 if(progress == 0)
7178 return 0;
7179 if(buflen <= progress + 1 || buf[progress] != ':') {
7180 dim->max = dim->min;
7181 return progress;
7182 }
7183
7184 ++progress;
7185 size_t progress2 = UA_readNumber(buf: &buf[progress], buflen: buflen - progress, number: &dim->max);
7186 if(progress2 == 0)
7187 return 0;
7188
7189 /* invalid range */
7190 if(dim->min >= dim->max)
7191 return 0;
7192
7193 return progress + progress2;
7194}
7195
7196UA_StatusCode
7197UA_NumericRange_parse(UA_NumericRange *range, const UA_String str) {
7198 size_t idx = 0;
7199 size_t dimensionsMax = 0;
7200 UA_NumericRangeDimension *dimensions = NULL;
7201 UA_StatusCode retval = UA_STATUSCODE_GOOD;
7202 size_t offset = 0;
7203 while(true) {
7204 /* alloc dimensions */
7205 if(idx >= dimensionsMax) {
7206 UA_NumericRangeDimension *newds;
7207 size_t newdssize = sizeof(UA_NumericRangeDimension) * (dimensionsMax + 2);
7208 newds = (UA_NumericRangeDimension*)UA_realloc(ptr: dimensions, size: newdssize);
7209 if(!newds) {
7210 retval = UA_STATUSCODE_BADOUTOFMEMORY;
7211 break;
7212 }
7213 dimensions = newds;
7214 dimensionsMax = dimensionsMax + 2;
7215 }
7216
7217 /* read the dimension */
7218 size_t progress = readDimension(buf: &str.data[offset], buflen: str.length - offset,
7219 dim: &dimensions[idx]);
7220 if(progress == 0) {
7221 retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
7222 break;
7223 }
7224 offset += progress;
7225 ++idx;
7226
7227 /* loop into the next dimension */
7228 if(offset >= str.length)
7229 break;
7230
7231 if(str.data[offset] != ',') {
7232 retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
7233 break;
7234 }
7235 ++offset;
7236 }
7237
7238 if(retval == UA_STATUSCODE_GOOD && idx > 0) {
7239 range->dimensions = dimensions;
7240 range->dimensionsSize = idx;
7241 } else {
7242 UA_free(ptr: dimensions);
7243 }
7244
7245 return retval;
7246}
7247
7248/**** amalgamated original file "/src/ua_types_encoding_binary.c" ****/
7249
7250/* This Source Code Form is subject to the terms of the Mozilla Public
7251 * License, v. 2.0. If a copy of the MPL was not distributed with this
7252 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7253 *
7254 * Copyright 2020 (c) Fraunhofer IOSB (Author: Andreas Ebner)
7255 * Copyright 2020 (c) Grigory Friedman
7256 * Copyright 2014-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
7257 * Copyright 2014-2017 (c) Florian Palm
7258 * Copyright 2014-2016 (c) Sten Grüner
7259 * Copyright 2014 (c) Leon Urbas
7260 * Copyright 2015 (c) LEvertz
7261 * Copyright 2015 (c) Chris Iatrou
7262 * Copyright 2015-2016 (c) Oleksiy Vasylyev
7263 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
7264 * Copyright 2016 (c) Lorenz Haas
7265 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
7266 * Copyright 2017 (c) Henrik Norrman
7267 */
7268
7269
7270
7271/**
7272 * Type Encoding and Decoding
7273 * --------------------------
7274 * The following methods contain encoding and decoding functions for the builtin
7275 * data types and generic functions that operate on all types and arrays. This
7276 * requires the type description from a UA_DataType structure.
7277 *
7278 * Breaking a message up into chunks is integrated with the encoding. When the
7279 * end of a buffer is reached, a callback is executed that sends the current
7280 * buffer as a chunk and exchanges the encoding buffer "underneath" the ongoing
7281 * encoding. This reduces the RAM requirements and unnecessary copying. */
7282
7283/* Part 6 §5.1.5: Decoders shall support at least 100 nesting levels */
7284#define UA_ENCODING_MAX_RECURSION 100
7285
7286typedef struct {
7287 /* Pointers to the current and last buffer position */
7288 u8 *pos;
7289 const u8 *end;
7290
7291 /* How often did we en-/decoding recurse? */
7292 u16 depth;
7293
7294 const UA_DataTypeArray *customTypes;
7295 UA_exchangeEncodeBuffer exchangeBufferCallback;
7296 void *exchangeBufferCallbackHandle;
7297} Ctx;
7298
7299typedef status
7300(*encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type,
7301 Ctx *UA_RESTRICT ctx);
7302typedef status
7303(*decodeBinarySignature)(void *UA_RESTRICT dst, const UA_DataType *type,
7304 Ctx *UA_RESTRICT ctx);
7305typedef size_t
7306(*calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *type);
7307
7308#define ENCODE_BINARY(TYPE) static status \
7309 TYPE##_encodeBinary(const UA_##TYPE *UA_RESTRICT src, \
7310 const UA_DataType *type, Ctx *UA_RESTRICT ctx)
7311#define DECODE_BINARY(TYPE) static status \
7312 TYPE##_decodeBinary(UA_##TYPE *UA_RESTRICT dst, \
7313 const UA_DataType *type, Ctx *UA_RESTRICT ctx)
7314#define CALCSIZE_BINARY(TYPE) static size_t \
7315 TYPE##_calcSizeBinary(const UA_##TYPE *UA_RESTRICT src, const UA_DataType *_)
7316#define ENCODE_DIRECT(SRC, TYPE) TYPE##_encodeBinary((const UA_##TYPE*)SRC, NULL, ctx)
7317#define DECODE_DIRECT(DST, TYPE) TYPE##_decodeBinary((UA_##TYPE*)DST, NULL, ctx)
7318
7319/* Jumptables for de-/encoding and computing the buffer length. The methods in
7320 * the decoding jumptable do not all clean up their allocated memory when an
7321 * error occurs. So a final _clear needs to be called before returning to the
7322 * user. */
7323extern const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS];
7324extern const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS];
7325extern const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS];
7326
7327/* Send the current chunk and replace the buffer */
7328static status exchangeBuffer(Ctx *ctx) {
7329 if(!ctx->exchangeBufferCallback)
7330 return UA_STATUSCODE_BADENCODINGERROR;
7331 return ctx->exchangeBufferCallback(ctx->exchangeBufferCallbackHandle,
7332 &ctx->pos, &ctx->end);
7333}
7334
7335/* If encoding fails, exchange the buffer and try again. */
7336static status
7337encodeWithExchangeBuffer(const void *ptr, const UA_DataType *type, Ctx *ctx) {
7338 u8 *oldpos = ctx->pos; /* Last known good position */
7339#ifndef NDEBUG
7340 /* We have to ensure that the buffer was not exchanged AND
7341 * BADENCODINGLIMITSEXCEEDED was returned. If that were the case, oldpos
7342 * would be invalid. That means, a type encoding must never return
7343 * BADENCODINGLIMITSEXCEEDED once the buffer could have been exchanged. This
7344 * is achieved by the use of encodeWithExchangeBuffer. */
7345 const u8 *oldend = ctx->end;
7346 (void)oldend; /* For compilers who don't understand NDEBUG... */
7347#endif
7348 status ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx);
7349 if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
7350 UA_assert(ctx->end == oldend);
7351 ctx->pos = oldpos; /* Set to the last known good position and exchange */
7352 ret = exchangeBuffer(ctx);
7353 UA_CHECK_STATUS(ret, return ret);
7354 ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx);
7355 }
7356 return ret;
7357}
7358
7359/*****************/
7360/* Integer Types */
7361/*****************/
7362
7363#if !UA_BINARY_OVERLAYABLE_INTEGER
7364
7365#pragma message "Integer endianness could not be detected to be little endian. Use slow generic encoding."
7366
7367/* These en/decoding functions are only used when the architecture isn't little-endian. */
7368static void
7369UA_encode16(const u16 v, u8 buf[2]) {
7370 buf[0] = (u8)v;
7371 buf[1] = (u8)(v >> 8);
7372}
7373
7374static void
7375UA_decode16(const u8 buf[2], u16 *v) {
7376 *v = (u16)((u16)buf[0] + (((u16)buf[1]) << 8));
7377}
7378
7379static void
7380UA_encode32(const u32 v, u8 buf[4]) {
7381 buf[0] = (u8)v;
7382 buf[1] = (u8)(v >> 8);
7383 buf[2] = (u8)(v >> 16);
7384 buf[3] = (u8)(v >> 24);
7385}
7386
7387static void
7388UA_decode32(const u8 buf[4], u32 *v) {
7389 *v = (u32)((u32)buf[0] + (((u32)buf[1]) << 8) +
7390 (((u32)buf[2]) << 16) + (((u32)buf[3]) << 24));
7391}
7392
7393static void
7394UA_encode64(const u64 v, u8 buf[8]) {
7395 buf[0] = (u8)v;
7396 buf[1] = (u8)(v >> 8);
7397 buf[2] = (u8)(v >> 16);
7398 buf[3] = (u8)(v >> 24);
7399 buf[4] = (u8)(v >> 32);
7400 buf[5] = (u8)(v >> 40);
7401 buf[6] = (u8)(v >> 48);
7402 buf[7] = (u8)(v >> 56);
7403}
7404
7405static void
7406UA_decode64(const u8 buf[8], u64 *v) {
7407 *v = (u64)((u64)buf[0] + (((u64)buf[1]) << 8) +
7408 (((u64)buf[2]) << 16) + (((u64)buf[3]) << 24) +
7409 (((u64)buf[4]) << 32) + (((u64)buf[5]) << 40) +
7410 (((u64)buf[6]) << 48) + (((u64)buf[7]) << 56));
7411}
7412
7413#endif /* !UA_BINARY_OVERLAYABLE_INTEGER */
7414
7415/* Boolean */
7416/* Note that sizeof(bool) != 1 on some platforms. Overlayable integer encoding
7417 * is disabled in those cases. */
7418ENCODE_BINARY(Boolean) {
7419 UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7420 *ctx->pos = *(const u8*)src;
7421 ++ctx->pos;
7422 return UA_STATUSCODE_GOOD;
7423}
7424
7425DECODE_BINARY(Boolean) {
7426 UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADDECODINGERROR);
7427 *dst = (*ctx->pos > 0) ? true : false;
7428 ++ctx->pos;
7429 return UA_STATUSCODE_GOOD;
7430}
7431
7432/* Byte */
7433ENCODE_BINARY(Byte) {
7434 UA_CHECK(ctx->pos + sizeof(u8) <= ctx->end,
7435 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7436 *ctx->pos = *(const u8*)src;
7437 ++ctx->pos;
7438 return UA_STATUSCODE_GOOD;
7439}
7440
7441DECODE_BINARY(Byte) {
7442 UA_CHECK(ctx->pos + sizeof(u8) <= ctx->end,
7443 return UA_STATUSCODE_BADDECODINGERROR);
7444 *dst = *ctx->pos;
7445 ++ctx->pos;
7446 return UA_STATUSCODE_GOOD;
7447}
7448
7449/* UInt16 */
7450ENCODE_BINARY(UInt16) {
7451 UA_CHECK(ctx->pos + sizeof(u16) <= ctx->end,
7452 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7453#if UA_BINARY_OVERLAYABLE_INTEGER
7454 memcpy(dest: ctx->pos, src: src, n: sizeof(u16));
7455#else
7456 UA_encode16(*src, ctx->pos);
7457#endif
7458 ctx->pos += 2;
7459 return UA_STATUSCODE_GOOD;
7460}
7461
7462DECODE_BINARY(UInt16) {
7463 UA_CHECK(ctx->pos + sizeof(u16) <= ctx->end,
7464 return UA_STATUSCODE_BADDECODINGERROR);
7465#if UA_BINARY_OVERLAYABLE_INTEGER
7466 memcpy(dest: dst, src: ctx->pos, n: sizeof(u16));
7467#else
7468 UA_decode16(ctx->pos, dst);
7469#endif
7470 ctx->pos += 2;
7471 return UA_STATUSCODE_GOOD;
7472}
7473
7474/* UInt32 */
7475ENCODE_BINARY(UInt32) {
7476 UA_CHECK(ctx->pos + sizeof(u32) <= ctx->end,
7477 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7478#if UA_BINARY_OVERLAYABLE_INTEGER
7479 memcpy(dest: ctx->pos, src: src, n: sizeof(u32));
7480#else
7481 UA_encode32(*src, ctx->pos);
7482#endif
7483 ctx->pos += 4;
7484 return UA_STATUSCODE_GOOD;
7485}
7486
7487DECODE_BINARY(UInt32) {
7488 UA_CHECK(ctx->pos + sizeof(u32) <= ctx->end,
7489 return UA_STATUSCODE_BADDECODINGERROR);
7490#if UA_BINARY_OVERLAYABLE_INTEGER
7491 memcpy(dest: dst, src: ctx->pos, n: sizeof(u32));
7492#else
7493 UA_decode32(ctx->pos, dst);
7494#endif
7495 ctx->pos += 4;
7496 return UA_STATUSCODE_GOOD;
7497}
7498
7499/* UInt64 */
7500ENCODE_BINARY(UInt64) {
7501 UA_CHECK(ctx->pos + sizeof(u64) <= ctx->end,
7502 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7503#if UA_BINARY_OVERLAYABLE_INTEGER
7504 memcpy(dest: ctx->pos, src: src, n: sizeof(u64));
7505#else
7506 UA_encode64(*src, ctx->pos);
7507#endif
7508 ctx->pos += 8;
7509 return UA_STATUSCODE_GOOD;
7510}
7511
7512DECODE_BINARY(UInt64) {
7513 UA_CHECK(ctx->pos + sizeof(u64) <= ctx->end,
7514 return UA_STATUSCODE_BADDECODINGERROR);
7515#if UA_BINARY_OVERLAYABLE_INTEGER
7516 memcpy(dest: dst, src: ctx->pos, n: sizeof(u64));
7517#else
7518 UA_decode64(ctx->pos, dst);
7519#endif
7520 ctx->pos += 8;
7521 return UA_STATUSCODE_GOOD;
7522}
7523
7524/************************/
7525/* Floating Point Types */
7526/************************/
7527
7528/* Can we reuse the integer encoding mechanism by casting floating point
7529 * values? */
7530#if (UA_FLOAT_IEEE754 == 1) && (UA_LITTLE_ENDIAN == UA_FLOAT_LITTLE_ENDIAN)
7531# define Float_encodeBinary UInt32_encodeBinary
7532# define Float_decodeBinary UInt32_decodeBinary
7533# define Double_encodeBinary UInt64_encodeBinary
7534# define Double_decodeBinary UInt64_decodeBinary
7535#else
7536
7537#include <math.h>
7538
7539#pragma message "No native IEEE 754 format detected. Use slow generic encoding."
7540
7541/* Handling of IEEE754 floating point values was taken from Beej's Guide to
7542 * Network Programming (http://beej.us/guide/bgnet/) and enhanced to cover the
7543 * edge cases +/-0, +/-inf and nan. */
7544static uint64_t
7545pack754(long double f, unsigned bits, unsigned expbits) {
7546 unsigned significandbits = bits - expbits - 1;
7547 long double fnorm;
7548 long long sign;
7549 if(f < 0) { sign = 1; fnorm = -f; }
7550 else { sign = 0; fnorm = f; }
7551 int shift = 0;
7552 while(fnorm >= 2.0) { fnorm /= 2.0; ++shift; }
7553 while(fnorm < 1.0) { fnorm *= 2.0; --shift; }
7554 fnorm = fnorm - 1.0;
7555 long long significand = (long long)(fnorm * ((float)(1LL<<significandbits) + 0.5f));
7556 long long exponent = shift + ((1<<(expbits-1)) - 1);
7557 return (uint64_t)((sign<<(bits-1)) | (exponent<<(bits-expbits-1)) | significand);
7558}
7559
7560static long double
7561unpack754(uint64_t i, unsigned bits, unsigned expbits) {
7562 unsigned significandbits = bits - expbits - 1;
7563 long double result = (long double)(i&(uint64_t)((1LL<<significandbits)-1));
7564 result /= (long double)(1LL<<significandbits);
7565 result += 1.0f;
7566 unsigned bias = (unsigned)(1<<(expbits-1)) - 1;
7567 long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias;
7568 while(shift > 0) { result *= 2.0; --shift; }
7569 while(shift < 0) { result /= 2.0; ++shift; }
7570 result *= ((i>>(bits-1))&1)? -1.0: 1.0;
7571 return result;
7572}
7573
7574/* Float */
7575#define FLOAT_NAN 0xffc00000
7576#define FLOAT_INF 0x7f800000
7577#define FLOAT_NEG_INF 0xff800000
7578#define FLOAT_NEG_ZERO 0x80000000
7579
7580ENCODE_BINARY(Float) {
7581 UA_Float f = *src;
7582 u32 encoded;
7583 /* cppcheck-suppress duplicateExpression */
7584 if(f != f) encoded = FLOAT_NAN;
7585 else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0;
7586 else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF;
7587 else encoded = (u32)pack754(f, 32, 8);
7588 return ENCODE_DIRECT(&encoded, UInt32);
7589}
7590
7591DECODE_BINARY(Float) {
7592 u32 decoded;
7593 status ret = DECODE_DIRECT(&decoded, UInt32);
7594 if(ret != UA_STATUSCODE_GOOD)
7595 return ret;
7596 if(decoded == 0) *dst = 0.0f;
7597 else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f;
7598 else if(decoded == FLOAT_INF) *dst = INFINITY;
7599 else if(decoded == FLOAT_NEG_INF) *dst = -INFINITY;
7600 else if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) ||
7601 (decoded >= 0xff800001)) *dst = NAN;
7602 else *dst = (UA_Float)unpack754(decoded, 32, 8);
7603 return UA_STATUSCODE_GOOD;
7604}
7605
7606/* Double */
7607#define DOUBLE_NAN 0xfff8000000000000L
7608#define DOUBLE_INF 0x7ff0000000000000L
7609#define DOUBLE_NEG_INF 0xfff0000000000000L
7610#define DOUBLE_NEG_ZERO 0x8000000000000000L
7611
7612ENCODE_BINARY(Double) {
7613 UA_Double d = *src;
7614 u64 encoded;
7615 /* cppcheck-suppress duplicateExpression */
7616 if(d != d) encoded = DOUBLE_NAN;
7617 else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0;
7618 else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF;
7619 else encoded = pack754(d, 64, 11);
7620 return ENCODE_DIRECT(&encoded, UInt64);
7621}
7622
7623DECODE_BINARY(Double) {
7624 u64 decoded;
7625 status ret = DECODE_DIRECT(&decoded, UInt64);
7626 UA_CHECK_STATUS(ret, return ret);
7627 if(decoded == 0) *dst = 0.0;
7628 else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0;
7629 else if(decoded == DOUBLE_INF) *dst = INFINITY;
7630 else if(decoded == DOUBLE_NEG_INF) *dst = -INFINITY;
7631 else if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) ||
7632 (decoded >= 0xfff0000000000001L)) *dst = NAN;
7633 else *dst = (UA_Double)unpack754(decoded, 64, 11);
7634 return UA_STATUSCODE_GOOD;
7635}
7636
7637#endif
7638
7639/******************/
7640/* Array Handling */
7641/******************/
7642
7643static status
7644Array_encodeBinaryOverlayable(uintptr_t ptr, size_t memSize, Ctx *ctx) {
7645 /* Loop as long as more elements remain than fit into the chunk */
7646 while(ctx->end < ctx->pos + memSize) {
7647 size_t possible = ((uintptr_t)ctx->end - (uintptr_t)ctx->pos);
7648 memcpy(dest: ctx->pos, src: (void*)ptr, n: possible);
7649 ctx->pos += possible;
7650 ptr += possible;
7651 status ret = exchangeBuffer(ctx);
7652 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7653 UA_CHECK_STATUS(ret, return ret);
7654 memSize -= possible;
7655 }
7656
7657 /* Encode the remaining elements */
7658 memcpy(dest: ctx->pos, src: (void*)ptr, n: memSize);
7659 ctx->pos += memSize;
7660 return UA_STATUSCODE_GOOD;
7661}
7662
7663static status
7664Array_encodeBinaryComplex(uintptr_t ptr, size_t length,
7665 const UA_DataType *type, Ctx *ctx) {
7666 /* Encode every element */
7667 for(size_t i = 0; i < length; ++i) {
7668 status ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type, ctx);
7669 ptr += type->memSize;
7670 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7671 UA_CHECK_STATUS(ret, return ret); /* Unrecoverable fail */
7672 }
7673 return UA_STATUSCODE_GOOD;
7674}
7675
7676static status
7677Array_encodeBinary(const void *src, size_t length, const UA_DataType *type, Ctx *ctx) {
7678 /* Check and convert the array length to int32 */
7679 i32 signed_length = -1;
7680 if(length > UA_INT32_MAX)
7681 return UA_STATUSCODE_BADINTERNALERROR;
7682 if(length > 0)
7683 signed_length = (i32)length;
7684 else if(src == UA_EMPTY_ARRAY_SENTINEL)
7685 signed_length = 0;
7686
7687 /* Encode the array length */
7688 status ret = encodeWithExchangeBuffer(ptr: &signed_length, type: &UA_TYPES[UA_TYPES_INT32], ctx);
7689 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7690 UA_CHECK_STATUS(ret, return ret);
7691
7692 /* Encode the content */
7693 if(length > 0) {
7694 if(type->overlayable)
7695 ret = Array_encodeBinaryOverlayable(ptr: (uintptr_t)src, memSize: length * type->memSize, ctx);
7696 else
7697 ret = Array_encodeBinaryComplex(ptr: (uintptr_t)src, length, type, ctx);
7698 }
7699 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7700 return ret;
7701}
7702
7703static status
7704Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length,
7705 const UA_DataType *type, Ctx *ctx) {
7706 /* Decode the length */
7707 i32 signed_length;
7708 status ret = DECODE_DIRECT(&signed_length, UInt32); /* Int32 */
7709 UA_CHECK_STATUS(ret, return ret);
7710
7711 /* Return early for empty arrays */
7712 if(signed_length <= 0) {
7713 *out_length = 0;
7714 if(signed_length < 0)
7715 *dst = NULL;
7716 else
7717 *dst = UA_EMPTY_ARRAY_SENTINEL;
7718 return UA_STATUSCODE_GOOD;
7719 }
7720
7721 /* Filter out arrays that can obviously not be decoded, because the message
7722 * is too small for the array length. This prevents the allocation of very
7723 * long arrays for bogus messages.*/
7724 size_t length = (size_t)signed_length;
7725 UA_CHECK(ctx->pos + ((type->memSize * length) / 32) <= ctx->end,
7726 return UA_STATUSCODE_BADDECODINGERROR);
7727
7728 /* Allocate memory */
7729 *dst = UA_calloc(nmemb: length, size: type->memSize);
7730 UA_CHECK_MEM(*dst, return UA_STATUSCODE_BADOUTOFMEMORY);
7731
7732 if(type->overlayable) {
7733 /* memcpy overlayable array */
7734 UA_CHECK(ctx->pos + (type->memSize * length) <= ctx->end,
7735 UA_free(*dst); *dst = NULL; return UA_STATUSCODE_BADDECODINGERROR);
7736 memcpy(dest: *dst, src: ctx->pos, n: type->memSize * length);
7737 ctx->pos += type->memSize * length;
7738 } else {
7739 /* Decode array members */
7740 uintptr_t ptr = (uintptr_t)*dst;
7741 for(size_t i = 0; i < length; ++i) {
7742 ret = decodeBinaryJumpTable[type->typeKind]((void*)ptr, type, ctx);
7743 UA_CHECK_STATUS(ret, /* +1 because last element is also already initialized */
7744 UA_Array_delete(*dst, i+1, type); *dst = NULL; return ret);
7745 ptr += type->memSize;
7746 }
7747 }
7748 *out_length = length;
7749 return UA_STATUSCODE_GOOD;
7750}
7751
7752/*****************/
7753/* Builtin Types */
7754/*****************/
7755
7756ENCODE_BINARY(String) {
7757 return Array_encodeBinary(src: src->data, length: src->length, type: &UA_TYPES[UA_TYPES_BYTE], ctx);
7758}
7759
7760DECODE_BINARY(String) {
7761 return Array_decodeBinary(dst: (void**)&dst->data, out_length: &dst->length, type: &UA_TYPES[UA_TYPES_BYTE], ctx);
7762}
7763
7764/* Guid */
7765ENCODE_BINARY(Guid) {
7766 status ret = UA_STATUSCODE_GOOD;
7767 ret |= ENCODE_DIRECT(&src->data1, UInt32);
7768 ret |= ENCODE_DIRECT(&src->data2, UInt16);
7769 ret |= ENCODE_DIRECT(&src->data3, UInt16);
7770 UA_CHECK(ctx->pos + (8*sizeof(u8)) <= ctx->end,
7771 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7772 memcpy(dest: ctx->pos, src: src->data4, n: 8*sizeof(u8));
7773 ctx->pos += 8;
7774 return ret;
7775}
7776
7777DECODE_BINARY(Guid) {
7778 status ret = UA_STATUSCODE_GOOD;
7779 ret |= DECODE_DIRECT(&dst->data1, UInt32);
7780 ret |= DECODE_DIRECT(&dst->data2, UInt16);
7781 ret |= DECODE_DIRECT(&dst->data3, UInt16);
7782 UA_CHECK(ctx->pos + (8*sizeof(u8)) <= ctx->end,
7783 return UA_STATUSCODE_BADDECODINGERROR);
7784 memcpy(dest: dst->data4, src: ctx->pos, n: 8*sizeof(u8));
7785 ctx->pos += 8;
7786 return ret;
7787}
7788
7789/* NodeId */
7790#define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0u
7791#define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1u
7792#define UA_NODEIDTYPE_NUMERIC_COMPLETE 2u
7793
7794#define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40u
7795#define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80u
7796
7797/* For ExpandedNodeId, we prefill the encoding mask. */
7798static status
7799NodeId_encodeBinaryWithEncodingMask(UA_NodeId const *src, u8 encoding, Ctx *ctx) {
7800 status ret = UA_STATUSCODE_GOOD;
7801 switch(src->identifierType) {
7802 case UA_NODEIDTYPE_NUMERIC:
7803 if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
7804 encoding |= UA_NODEIDTYPE_NUMERIC_COMPLETE;
7805 ret |= ENCODE_DIRECT(&encoding, Byte);
7806 ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7807 ret |= ENCODE_DIRECT(&src->identifier.numeric, UInt32);
7808 } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
7809 encoding |= UA_NODEIDTYPE_NUMERIC_FOURBYTE;
7810 ret |= ENCODE_DIRECT(&encoding, Byte);
7811 u8 nsindex = (u8)src->namespaceIndex;
7812 ret |= ENCODE_DIRECT(&nsindex, Byte);
7813 u16 identifier16 = (u16)src->identifier.numeric;
7814 ret |= ENCODE_DIRECT(&identifier16, UInt16);
7815 } else {
7816 encoding |= UA_NODEIDTYPE_NUMERIC_TWOBYTE;
7817 ret |= ENCODE_DIRECT(&encoding, Byte);
7818 u8 identifier8 = (u8)src->identifier.numeric;
7819 ret |= ENCODE_DIRECT(&identifier8, Byte);
7820 }
7821 break;
7822 case UA_NODEIDTYPE_STRING:
7823 encoding |= (u8)UA_NODEIDTYPE_STRING;
7824 ret |= ENCODE_DIRECT(&encoding, Byte);
7825 ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7826 UA_CHECK_STATUS(ret, return ret);
7827 /* Can exchange the buffer */
7828 ret = ENCODE_DIRECT(&src->identifier.string, String);
7829 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7830 break;
7831 case UA_NODEIDTYPE_GUID:
7832 encoding |= (u8)UA_NODEIDTYPE_GUID;
7833 ret |= ENCODE_DIRECT(&encoding, Byte);
7834 ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7835 ret |= ENCODE_DIRECT(&src->identifier.guid, Guid);
7836 break;
7837 case UA_NODEIDTYPE_BYTESTRING:
7838 encoding |= (u8)UA_NODEIDTYPE_BYTESTRING;
7839 ret |= ENCODE_DIRECT(&encoding, Byte);
7840 ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7841 UA_CHECK_STATUS(ret, return ret);
7842 /* Can exchange the buffer */
7843 ret = ENCODE_DIRECT(&src->identifier.byteString, String); /* ByteString */
7844 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7845 break;
7846 default:
7847 return UA_STATUSCODE_BADINTERNALERROR;
7848 }
7849 return ret;
7850}
7851
7852ENCODE_BINARY(NodeId) {
7853 return NodeId_encodeBinaryWithEncodingMask(src, encoding: 0, ctx);
7854}
7855
7856DECODE_BINARY(NodeId) {
7857 u8 dstByte = 0, encodingByte = 0;
7858 u16 dstUInt16 = 0;
7859
7860 /* Decode the encoding bitfield */
7861 status ret = DECODE_DIRECT(&encodingByte, Byte);
7862 UA_CHECK_STATUS(ret, return ret);
7863
7864 /* Filter out the bits used only for ExpandedNodeIds */
7865 encodingByte &= (u8)~(u8)(UA_EXPANDEDNODEID_SERVERINDEX_FLAG |
7866 UA_EXPANDEDNODEID_NAMESPACEURI_FLAG);
7867
7868 /* Decode the namespace and identifier */
7869 switch(encodingByte) {
7870 case UA_NODEIDTYPE_NUMERIC_TWOBYTE:
7871 dst->identifierType = UA_NODEIDTYPE_NUMERIC;
7872 ret = DECODE_DIRECT(&dstByte, Byte);
7873 dst->identifier.numeric = dstByte;
7874 dst->namespaceIndex = 0;
7875 break;
7876 case UA_NODEIDTYPE_NUMERIC_FOURBYTE:
7877 dst->identifierType = UA_NODEIDTYPE_NUMERIC;
7878 ret |= DECODE_DIRECT(&dstByte, Byte);
7879 dst->namespaceIndex = dstByte;
7880 ret |= DECODE_DIRECT(&dstUInt16, UInt16);
7881 dst->identifier.numeric = dstUInt16;
7882 break;
7883 case UA_NODEIDTYPE_NUMERIC_COMPLETE:
7884 dst->identifierType = UA_NODEIDTYPE_NUMERIC;
7885 ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7886 ret |= DECODE_DIRECT(&dst->identifier.numeric, UInt32);
7887 break;
7888 case UA_NODEIDTYPE_STRING:
7889 dst->identifierType = UA_NODEIDTYPE_STRING;
7890 ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7891 ret |= DECODE_DIRECT(&dst->identifier.string, String);
7892 break;
7893 case UA_NODEIDTYPE_GUID:
7894 dst->identifierType = UA_NODEIDTYPE_GUID;
7895 ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7896 ret |= DECODE_DIRECT(&dst->identifier.guid, Guid);
7897 break;
7898 case UA_NODEIDTYPE_BYTESTRING:
7899 dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
7900 ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7901 ret |= DECODE_DIRECT(&dst->identifier.byteString, String); /* ByteString */
7902 break;
7903 default:
7904 ret |= UA_STATUSCODE_BADINTERNALERROR;
7905 break;
7906 }
7907 return ret;
7908}
7909
7910/* ExpandedNodeId */
7911ENCODE_BINARY(ExpandedNodeId) {
7912 /* Set up the encoding mask */
7913 u8 encoding = 0;
7914 if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL)
7915 encoding |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
7916 if(src->serverIndex > 0)
7917 encoding |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
7918
7919 /* Encode the NodeId. Can exchange the buffer. */
7920 status ret = NodeId_encodeBinaryWithEncodingMask(src: &src->nodeId, encoding, ctx);
7921 UA_CHECK_STATUS(ret, return ret);
7922
7923 /* Encode the namespace. Internally uses encodeWithExchangeBuffer
7924 * everywhere. So it will never return
7925 * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. */
7926 if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL) {
7927 ret = ENCODE_DIRECT(&src->namespaceUri, String);
7928 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7929 UA_CHECK_STATUS(ret, return ret);
7930 }
7931
7932 /* Encode the serverIndex */
7933 if(src->serverIndex > 0)
7934 ret = encodeWithExchangeBuffer(ptr: &src->serverIndex, type: &UA_TYPES[UA_TYPES_UINT32], ctx);
7935 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7936 return ret;
7937}
7938
7939DECODE_BINARY(ExpandedNodeId) {
7940 /* Decode the encoding mask */
7941 UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADDECODINGERROR);
7942 u8 encoding = *ctx->pos;
7943
7944 /* Decode the NodeId */
7945 status ret = DECODE_DIRECT(&dst->nodeId, NodeId);
7946
7947 /* Decode the NamespaceUri */
7948 if(encoding & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
7949 dst->nodeId.namespaceIndex = 0;
7950 ret |= DECODE_DIRECT(&dst->namespaceUri, String);
7951 }
7952
7953 /* Decode the ServerIndex */
7954 if(encoding & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
7955 ret |= DECODE_DIRECT(&dst->serverIndex, UInt32);
7956 return ret;
7957}
7958
7959/* QualifiedName */
7960ENCODE_BINARY(QualifiedName) {
7961 status ret = ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7962 /* Must check here so we can exchange the buffer in the string encoding */
7963 UA_CHECK_STATUS(ret, return ret);
7964 ret |= ENCODE_DIRECT(&src->name, String);
7965 return ret;
7966}
7967
7968DECODE_BINARY(QualifiedName) {
7969 status ret = DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7970 ret |= DECODE_DIRECT(&dst->name, String);
7971 return ret;
7972}
7973
7974/* LocalizedText */
7975#define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01u
7976#define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02u
7977
7978ENCODE_BINARY(LocalizedText) {
7979 /* Set up the encoding mask */
7980 u8 encoding = 0;
7981 if(src->locale.data)
7982 encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
7983 if(src->text.data)
7984 encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
7985
7986 /* Encode the encoding byte */
7987 status ret = ENCODE_DIRECT(&encoding, Byte);
7988 /* Must check here so we can exchange the buffer in the string encoding */
7989 UA_CHECK_STATUS(ret, return ret);
7990
7991 /* Encode the strings */
7992 if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
7993 ret |= ENCODE_DIRECT(&src->locale, String);
7994 if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
7995 ret |= ENCODE_DIRECT(&src->text, String);
7996 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7997 return ret;
7998}
7999
8000DECODE_BINARY(LocalizedText) {
8001 /* Decode the encoding mask */
8002 u8 encoding = 0;
8003 status ret = DECODE_DIRECT(&encoding, Byte);
8004
8005 /* Decode the content */
8006 if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
8007 ret |= DECODE_DIRECT(&dst->locale, String);
8008 if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
8009 ret |= DECODE_DIRECT(&dst->text, String);
8010 return ret;
8011}
8012
8013/* The binary encoding has a different nodeid from the data type. So it is not
8014 * possible to reuse UA_findDataType */
8015static const UA_DataType *
8016UA_findDataTypeByBinaryInternal(const UA_NodeId *typeId, Ctx *ctx) {
8017 /* Always look in the built-in types first. Assume that only numeric
8018 * identifiers are used for the builtin types. (They may contain data types
8019 * from all namespaces though.) */
8020 if(typeId->identifierType == UA_NODEIDTYPE_NUMERIC) {
8021 for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
8022 if(UA_TYPES[i].binaryEncodingId.identifier.numeric == typeId->identifier.numeric &&
8023 UA_TYPES[i].binaryEncodingId.namespaceIndex == typeId->namespaceIndex)
8024 return &UA_TYPES[i];
8025 }
8026 }
8027
8028 const UA_DataTypeArray *customTypes = ctx->customTypes;
8029 while(customTypes) {
8030 for(size_t i = 0; i < customTypes->typesSize; ++i) {
8031 if(UA_NodeId_equal(n1: typeId, n2: &customTypes->types[i].binaryEncodingId))
8032 return &customTypes->types[i];
8033 }
8034 customTypes = customTypes->next;
8035 }
8036
8037 return NULL;
8038}
8039
8040const UA_DataType *
8041UA_findDataTypeByBinary(const UA_NodeId *typeId) {
8042 Ctx ctx;
8043 ctx.customTypes = NULL;
8044 return UA_findDataTypeByBinaryInternal(typeId, ctx: &ctx);
8045}
8046
8047/* ExtensionObject */
8048ENCODE_BINARY(ExtensionObject) {
8049 u8 encoding = (u8)src->encoding;
8050
8051 /* No content or already encoded content. */
8052 if(encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
8053 /* Can exchange the buffer */
8054 status ret = ENCODE_DIRECT(&src->content.encoded.typeId, NodeId);
8055 UA_CHECK_STATUS(ret, return ret);
8056 ret = encodeWithExchangeBuffer(ptr: &encoding, type: &UA_TYPES[UA_TYPES_BYTE], ctx);
8057 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8058 UA_CHECK_STATUS(ret, return ret);
8059 switch(src->encoding) {
8060 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
8061 break;
8062 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
8063 case UA_EXTENSIONOBJECT_ENCODED_XML:
8064 /* ByteString in disguise. Array encoding can exchange the buffer */
8065 ret = ENCODE_DIRECT(&src->content.encoded.body, String);
8066 break;
8067 default:
8068 ret = UA_STATUSCODE_BADINTERNALERROR;
8069 }
8070 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8071 return ret;
8072 }
8073
8074 /* Cannot encode with no data or no type description */
8075 if(!src->content.decoded.type || !src->content.decoded.data)
8076 return UA_STATUSCODE_BADENCODINGERROR;
8077
8078 /* Write the NodeId for the binary encoded type. This could perform a buffer
8079 * exchange, but can also return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. */
8080 status ret = ENCODE_DIRECT(&src->content.decoded.type->binaryEncodingId, NodeId);
8081 UA_CHECK_STATUS(ret, return ret);
8082
8083 /* Encode the encoding byte */
8084 encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
8085 ret = encodeWithExchangeBuffer(ptr: &encoding, type: &UA_TYPES[UA_TYPES_BYTE], ctx);
8086 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8087 UA_CHECK_STATUS(ret, return ret);
8088
8089 /* Encode the content length */
8090 const UA_DataType *contentType = src->content.decoded.type;
8091 size_t len = UA_calcSizeBinary(p: src->content.decoded.data, type: contentType);
8092 UA_CHECK(len <= UA_INT32_MAX, return UA_STATUSCODE_BADENCODINGERROR);
8093 i32 signed_len = (i32)len;
8094 ret = encodeWithExchangeBuffer(ptr: &signed_len, type: &UA_TYPES[UA_TYPES_INT32], ctx);
8095 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8096 UA_CHECK_STATUS(ret, return ret);
8097
8098 /* Encode the content */
8099 ret = encodeWithExchangeBuffer(ptr: src->content.decoded.data, type: contentType, ctx);
8100 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8101 return ret;
8102}
8103
8104static status
8105ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId,
8106 Ctx *ctx) {
8107 /* Lookup the datatype */
8108 const UA_DataType *type = UA_findDataTypeByBinaryInternal(typeId, ctx);
8109
8110 /* Unknown type, just take the binary content */
8111 if(!type) {
8112 dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
8113 UA_NodeId_copy(src: typeId, dst: &dst->content.encoded.typeId);
8114 return DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
8115 }
8116
8117 /* Allocate memory */
8118 dst->content.decoded.data = UA_new(type);
8119 UA_CHECK_MEM(dst->content.decoded.data, return UA_STATUSCODE_BADOUTOFMEMORY);
8120
8121 /* Jump over the length field (TODO: check if the decoded length matches) */
8122 ctx->pos += 4;
8123
8124 /* Decode */
8125 dst->encoding = UA_EXTENSIONOBJECT_DECODED;
8126 dst->content.decoded.type = type;
8127 return decodeBinaryJumpTable[type->typeKind](dst->content.decoded.data, type, ctx);
8128}
8129
8130DECODE_BINARY(ExtensionObject) {
8131 u8 encoding = 0;
8132 UA_NodeId binTypeId;
8133 UA_NodeId_init(p: &binTypeId);
8134
8135 status ret = UA_STATUSCODE_GOOD;
8136 ret |= DECODE_DIRECT(&binTypeId, NodeId);
8137 ret |= DECODE_DIRECT(&encoding, Byte);
8138 UA_CHECK_STATUS(ret, UA_NodeId_clear(&binTypeId); return ret);
8139
8140 switch(encoding) {
8141 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
8142 ret = ExtensionObject_decodeBinaryContent(dst, typeId: &binTypeId, ctx);
8143 UA_NodeId_clear(p: &binTypeId);
8144 break;
8145 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
8146 dst->encoding = (UA_ExtensionObjectEncoding)encoding;
8147 dst->content.encoded.typeId = binTypeId; /* move to dst */
8148 dst->content.encoded.body = UA_BYTESTRING_NULL;
8149 break;
8150 case UA_EXTENSIONOBJECT_ENCODED_XML:
8151 dst->encoding = (UA_ExtensionObjectEncoding)encoding;
8152 dst->content.encoded.typeId = binTypeId; /* move to dst */
8153 ret = DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
8154 UA_CHECK_STATUS(ret, UA_NodeId_clear(&dst->content.encoded.typeId));
8155 break;
8156 default:
8157 UA_NodeId_clear(p: &binTypeId);
8158 ret = UA_STATUSCODE_BADDECODINGERROR;
8159 break;
8160 }
8161
8162 return ret;
8163}
8164
8165/* Variant */
8166
8167static status
8168Variant_encodeBinaryWrapExtensionObject(const UA_Variant *src,
8169 const UA_Boolean isArray, Ctx *ctx) {
8170 size_t length = 1; /* Default to 1 for a scalar. */
8171
8172 /* Encode the array length if required */
8173 status ret = UA_STATUSCODE_GOOD;
8174 if(isArray) {
8175 UA_CHECK(src->arrayLength <= UA_INT32_MAX, return UA_STATUSCODE_BADENCODINGERROR);
8176 length = src->arrayLength;
8177 i32 encodedLength = (i32)src->arrayLength;
8178 ret = ENCODE_DIRECT(&encodedLength, UInt32); /* Int32 */
8179 UA_CHECK_STATUS(ret, return ret);
8180 }
8181
8182 /* Set up the ExtensionObject */
8183 UA_ExtensionObject eo;
8184 UA_ExtensionObject_init(p: &eo);
8185 eo.encoding = UA_EXTENSIONOBJECT_DECODED;
8186 eo.content.decoded.type = src->type;
8187 const u16 memSize = src->type->memSize;
8188 uintptr_t ptr = (uintptr_t)src->data;
8189
8190 /* Iterate over the array */
8191 for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) {
8192 eo.content.decoded.data = (void*)ptr;
8193 ret = encodeWithExchangeBuffer(ptr: &eo, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], ctx);
8194 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8195 ptr += memSize;
8196 }
8197 return ret;
8198}
8199
8200enum UA_VARIANT_ENCODINGMASKTYPE {
8201 UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3Fu, /* bits 0:5 */
8202 UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS = (u8)(0x01u << 6u), /* bit 6 */
8203 UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (u8)(0x01u << 7u) /* bit 7 */
8204};
8205
8206ENCODE_BINARY(Variant) {
8207 /* Quit early for the empty variant */
8208 u8 encoding = 0;
8209 if(!src->type)
8210 return ENCODE_DIRECT(&encoding, Byte);
8211
8212 /* Set the content type in the encoding mask */
8213 const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO);
8214 const UA_Boolean isEnum = (src->type->typeKind == UA_DATATYPEKIND_ENUM);
8215 if(isBuiltin)
8216 encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(src->type->typeKind + 1u)));
8217 else if(isEnum)
8218 encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_INT32 + 1u)));
8219 else
8220 encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_EXTENSIONOBJECT + 1u)));
8221
8222 /* Set the array type in the encoding mask */
8223 const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
8224 const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
8225 if(isArray) {
8226 encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
8227 if(hasDimensions)
8228 encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
8229 }
8230
8231 /* Encode the encoding byte */
8232 status ret = ENCODE_DIRECT(&encoding, Byte);
8233 UA_CHECK_STATUS(ret, return ret);
8234
8235 /* Encode the content. This can exchange the buffer. */
8236 if(!isBuiltin && !isEnum) {
8237 /* This could return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. But we
8238 * have not exchanged the buffer so far. */
8239 ret = Variant_encodeBinaryWrapExtensionObject(src, isArray, ctx);
8240 } else if(!isArray) {
8241 ret = encodeWithExchangeBuffer(ptr: src->data, type: src->type, ctx);
8242 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8243 } else {
8244 ret = Array_encodeBinary(src: src->data, length: src->arrayLength, type: src->type, ctx);
8245 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8246 }
8247 UA_CHECK_STATUS(ret, return ret);
8248
8249 /* Encode the array dimensions */
8250 if(hasDimensions && ret == UA_STATUSCODE_GOOD)
8251 ret = Array_encodeBinary(src: src->arrayDimensions, length: src->arrayDimensionsSize,
8252 type: &UA_TYPES[UA_TYPES_INT32], ctx);
8253 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8254 return ret;
8255}
8256
8257static status
8258Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst, Ctx *ctx) {
8259 /* Save the position in the ByteString. If unwrapping is not possible, start
8260 * from here to decode a normal ExtensionObject. */
8261 u8 *old_pos = ctx->pos;
8262
8263 /* Decode the DataType */
8264 UA_NodeId typeId;
8265 UA_NodeId_init(p: &typeId);
8266 status ret = DECODE_DIRECT(&typeId, NodeId);
8267 UA_CHECK_STATUS(ret, return ret);
8268
8269 /* Decode the EncodingByte */
8270 u8 encoding;
8271 ret = DECODE_DIRECT(&encoding, Byte);
8272 UA_CHECK_STATUS(ret, UA_NodeId_clear(&typeId); return ret);
8273
8274 /* Search for the datatype. Default to ExtensionObject. */
8275 if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
8276 (dst->type = UA_findDataTypeByBinaryInternal(typeId: &typeId, ctx)) != NULL) {
8277 /* Jump over the length field (TODO: check if length matches) */
8278 ctx->pos += 4;
8279 } else {
8280 /* Reset and decode as ExtensionObject */
8281 dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
8282 ctx->pos = old_pos;
8283 }
8284 UA_NodeId_clear(p: &typeId);
8285
8286 /* Allocate memory */
8287 dst->data = UA_new(type: dst->type);
8288 UA_CHECK_MEM(dst->data, return UA_STATUSCODE_BADOUTOFMEMORY);
8289
8290 /* Decode the content */
8291 return decodeBinaryJumpTable[dst->type->typeKind](dst->data, dst->type, ctx);
8292}
8293
8294/* The resulting variant always has the storagetype UA_VARIANT_DATA. */
8295DECODE_BINARY(Variant) {
8296 /* Decode the encoding byte */
8297 u8 encodingByte;
8298 status ret = DECODE_DIRECT(&encodingByte, Byte);
8299 UA_CHECK_STATUS(ret, return ret);
8300
8301 /* Return early for an empty variant (was already _inited) */
8302 if(encodingByte == 0)
8303 return UA_STATUSCODE_GOOD;
8304
8305 /* Does the variant contain an array? */
8306 const UA_Boolean isArray = (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY) > 0;
8307
8308 /* Get the datatype of the content. The type must be a builtin data type.
8309 * All not-builtin types are wrapped in an ExtensionObject. The "type kind"
8310 * for types up to DiagnsticInfo equals to the index in the encoding
8311 * byte. */
8312 size_t typeKind = (size_t)((encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
8313 UA_CHECK(typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO, return UA_STATUSCODE_BADDECODINGERROR);
8314
8315 /* A variant cannot contain a variant. But it can contain an array of
8316 * variants */
8317 UA_CHECK(typeKind != UA_DATATYPEKIND_VARIANT || isArray,
8318 return UA_STATUSCODE_BADDECODINGERROR);
8319
8320 /* Check the recursion limit */
8321 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
8322 ctx->depth++;
8323
8324 /* Decode the content */
8325 dst->type = &UA_TYPES[typeKind];
8326 if(isArray) {
8327 ret = Array_decodeBinary(dst: &dst->data, out_length: &dst->arrayLength, type: dst->type, ctx);
8328 } else if(typeKind != UA_DATATYPEKIND_EXTENSIONOBJECT) {
8329 dst->data = UA_new(type: dst->type);
8330 UA_CHECK_MEM(dst->data, ctx->depth--; return UA_STATUSCODE_BADOUTOFMEMORY);
8331 ret = decodeBinaryJumpTable[typeKind](dst->data, dst->type, ctx);
8332 } else {
8333 ret = Variant_decodeBinaryUnwrapExtensionObject(dst, ctx);
8334 }
8335
8336 /* Decode array dimensions */
8337 if(isArray && (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0)
8338 ret |= Array_decodeBinary(dst: (void**)&dst->arrayDimensions, out_length: &dst->arrayDimensionsSize,
8339 type: &UA_TYPES[UA_TYPES_INT32], ctx);
8340
8341 ctx->depth--;
8342 return ret;
8343}
8344
8345/* DataValue */
8346ENCODE_BINARY(DataValue) {
8347 /* Set up the encoding mask */
8348 u8 encodingMask = src->hasValue;
8349 encodingMask |= (u8)(src->hasStatus << 1u);
8350 encodingMask |= (u8)(src->hasSourceTimestamp << 2u);
8351 encodingMask |= (u8)(src->hasServerTimestamp << 3u);
8352 encodingMask |= (u8)(src->hasSourcePicoseconds << 4u);
8353 encodingMask |= (u8)(src->hasServerPicoseconds << 5u);
8354
8355 /* Encode the encoding byte */
8356 status ret = ENCODE_DIRECT(&encodingMask, Byte);
8357 UA_CHECK_STATUS(ret, return ret);
8358
8359 /* Encode the variant. */
8360 if(src->hasValue) {
8361 ret = ENCODE_DIRECT(&src->value, Variant);
8362 if(ret != UA_STATUSCODE_GOOD)
8363 return ret;
8364 }
8365
8366 if(src->hasStatus)
8367 ret |= encodeWithExchangeBuffer(ptr: &src->status, type: &UA_TYPES[UA_TYPES_STATUSCODE], ctx);
8368 if(src->hasSourceTimestamp)
8369 ret |= encodeWithExchangeBuffer(ptr: &src->sourceTimestamp, type: &UA_TYPES[UA_TYPES_DATETIME], ctx);
8370 if(src->hasSourcePicoseconds)
8371 ret |= encodeWithExchangeBuffer(ptr: &src->sourcePicoseconds, type: &UA_TYPES[UA_TYPES_UINT16], ctx);
8372 if(src->hasServerTimestamp)
8373 ret |= encodeWithExchangeBuffer(ptr: &src->serverTimestamp, type: &UA_TYPES[UA_TYPES_DATETIME], ctx);
8374 if(src->hasServerPicoseconds)
8375 ret |= encodeWithExchangeBuffer(ptr: &src->serverPicoseconds, type: &UA_TYPES[UA_TYPES_UINT16], ctx);
8376 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8377 return ret;
8378}
8379
8380#define MAX_PICO_SECONDS 9999
8381
8382DECODE_BINARY(DataValue) {
8383 /* Decode the encoding mask */
8384 u8 encodingMask;
8385 status ret = DECODE_DIRECT(&encodingMask, Byte);
8386 UA_CHECK_STATUS(ret, return ret);
8387
8388 /* Check the recursion limit */
8389 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
8390 ctx->depth++;
8391
8392 /* Decode the content */
8393 if(encodingMask & 0x01u) {
8394 dst->hasValue = true;
8395 ret |= DECODE_DIRECT(&dst->value, Variant);
8396 }
8397 if(encodingMask & 0x02u) {
8398 dst->hasStatus = true;
8399 ret |= DECODE_DIRECT(&dst->status, UInt32); /* StatusCode */
8400 }
8401 if(encodingMask & 0x04u) {
8402 dst->hasSourceTimestamp = true;
8403 ret |= DECODE_DIRECT(&dst->sourceTimestamp, UInt64); /* DateTime */
8404 }
8405 if(encodingMask & 0x10u) {
8406 dst->hasSourcePicoseconds = true;
8407 ret |= DECODE_DIRECT(&dst->sourcePicoseconds, UInt16);
8408 if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
8409 dst->sourcePicoseconds = MAX_PICO_SECONDS;
8410 }
8411 if(encodingMask & 0x08u) {
8412 dst->hasServerTimestamp = true;
8413 ret |= DECODE_DIRECT(&dst->serverTimestamp, UInt64); /* DateTime */
8414 }
8415 if(encodingMask & 0x20u) {
8416 dst->hasServerPicoseconds = true;
8417 ret |= DECODE_DIRECT(&dst->serverPicoseconds, UInt16);
8418 if(dst->serverPicoseconds > MAX_PICO_SECONDS)
8419 dst->serverPicoseconds = MAX_PICO_SECONDS;
8420 }
8421
8422 ctx->depth--;
8423 return ret;
8424}
8425
8426/* DiagnosticInfo */
8427ENCODE_BINARY(DiagnosticInfo) {
8428 /* Set up the encoding mask */
8429 u8 encodingMask = src->hasSymbolicId;
8430 encodingMask |= (u8)(src->hasNamespaceUri << 1u);
8431 encodingMask |= (u8)(src->hasLocalizedText << 2u);
8432 encodingMask |= (u8)(src->hasLocale << 3u);
8433 encodingMask |= (u8)(src->hasAdditionalInfo << 4u);
8434 encodingMask |= (u8)(src->hasInnerStatusCode << 5u);
8435 encodingMask |= (u8)(src->hasInnerDiagnosticInfo << 6u);
8436
8437 /* Encode the numeric content */
8438 status ret = ENCODE_DIRECT(&encodingMask, Byte);
8439 if(src->hasSymbolicId)
8440 ret |= ENCODE_DIRECT(&src->symbolicId, UInt32); /* Int32 */
8441 if(src->hasNamespaceUri)
8442 ret |= ENCODE_DIRECT(&src->namespaceUri, UInt32); /* Int32 */
8443 if(src->hasLocalizedText)
8444 ret |= ENCODE_DIRECT(&src->localizedText, UInt32); /* Int32 */
8445 if(src->hasLocale)
8446 ret |= ENCODE_DIRECT(&src->locale, UInt32); /* Int32 */
8447 if(ret != UA_STATUSCODE_GOOD)
8448 return ret;
8449
8450 /* Encode the additional info. Can exchange the buffer. */
8451 if(src->hasAdditionalInfo) {
8452 ret = ENCODE_DIRECT(&src->additionalInfo, String);
8453 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8454 UA_CHECK_STATUS(ret, return ret);
8455 }
8456
8457 /* Encode the inner status code */
8458 if(src->hasInnerStatusCode) {
8459 ret = encodeWithExchangeBuffer(ptr: &src->innerStatusCode, type: &UA_TYPES[UA_TYPES_UINT32], ctx);
8460 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8461 UA_CHECK_STATUS(ret, return ret);
8462 }
8463
8464 /* Encode the inner diagnostic info */
8465 if(src->hasInnerDiagnosticInfo) {
8466 ret = encodeWithExchangeBuffer(ptr: src->innerDiagnosticInfo,
8467 type: &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], ctx);
8468 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8469 }
8470
8471 return ret;
8472}
8473
8474DECODE_BINARY(DiagnosticInfo) {
8475 /* Decode the encoding mask */
8476 u8 encodingMask;
8477 status ret = DECODE_DIRECT(&encodingMask, Byte);
8478 UA_CHECK_STATUS(ret, return ret);
8479
8480 /* Decode the content */
8481 if(encodingMask & 0x01u) {
8482 dst->hasSymbolicId = true;
8483 ret |= DECODE_DIRECT(&dst->symbolicId, UInt32); /* Int32 */
8484 }
8485 if(encodingMask & 0x02u) {
8486 dst->hasNamespaceUri = true;
8487 ret |= DECODE_DIRECT(&dst->namespaceUri, UInt32); /* Int32 */
8488 }
8489 if(encodingMask & 0x04u) {
8490 dst->hasLocalizedText = true;
8491 ret |= DECODE_DIRECT(&dst->localizedText, UInt32); /* Int32 */
8492 }
8493 if(encodingMask & 0x08u) {
8494 dst->hasLocale = true;
8495 ret |= DECODE_DIRECT(&dst->locale, UInt32); /* Int32 */
8496 }
8497 if(encodingMask & 0x10u) {
8498 dst->hasAdditionalInfo = true;
8499 ret |= DECODE_DIRECT(&dst->additionalInfo, String);
8500 }
8501 if(encodingMask & 0x20u) {
8502 dst->hasInnerStatusCode = true;
8503 ret |= DECODE_DIRECT(&dst->innerStatusCode, UInt32); /* StatusCode */
8504 }
8505 if(encodingMask & 0x40u) {
8506 /* innerDiagnosticInfo is allocated on the heap */
8507 dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)
8508 UA_calloc(nmemb: 1, size: sizeof(UA_DiagnosticInfo));
8509 UA_CHECK_MEM(dst->innerDiagnosticInfo, return UA_STATUSCODE_BADOUTOFMEMORY);
8510 dst->hasInnerDiagnosticInfo = true;
8511
8512 /* Check the recursion limit */
8513 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8514 return UA_STATUSCODE_BADENCODINGERROR);
8515
8516 ctx->depth++;
8517 ret |= DECODE_DIRECT(dst->innerDiagnosticInfo, DiagnosticInfo);
8518 ctx->depth--;
8519 }
8520 return ret;
8521}
8522
8523/********************/
8524/* Structured Types */
8525/********************/
8526
8527static status
8528encodeBinaryStruct(const void *src, const UA_DataType *type, Ctx *ctx) {
8529 /* Check the recursion limit */
8530 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8531 return UA_STATUSCODE_BADENCODINGERROR);
8532 ctx->depth++;
8533
8534 /* Loop over members */
8535 uintptr_t ptr = (uintptr_t)src;
8536 status ret = UA_STATUSCODE_GOOD;
8537 for(size_t i = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
8538 const UA_DataTypeMember *m = &type->members[i];
8539 const UA_DataType *mt = m->memberType;
8540 ptr += m->padding;
8541
8542 /* Array. Buffer-exchange is done inside Array_encodeBinary if required. */
8543 if(m->isArray) {
8544 const size_t length = *((const size_t*)ptr);
8545 ptr += sizeof(size_t);
8546 ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt, ctx);
8547 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8548 ptr += sizeof(void*);
8549 continue;
8550 }
8551
8552 /* Scalar */
8553 ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx);
8554 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8555 ptr += mt->memSize;
8556 }
8557
8558 ctx->depth--;
8559 return ret;
8560}
8561
8562static status
8563encodeBinaryStructWithOptFields(const void *src, const UA_DataType *type, Ctx *ctx) {
8564 /* Check the recursion limit */
8565 if(ctx->depth > UA_ENCODING_MAX_RECURSION)
8566 return UA_STATUSCODE_BADENCODINGERROR;
8567 ctx->depth++;
8568
8569 /* Creating the encoding mask, marking the available optional fields */
8570 uintptr_t ptr = (uintptr_t)src;
8571 size_t optFieldCounter = 0;
8572 UA_UInt32 encodingMask = 0;
8573 for(size_t j = 0; j < type->membersSize; ++j) {
8574 const UA_DataTypeMember *m = &type->members[j];
8575 const UA_DataType *mt = m->memberType;
8576 ptr += m->padding;
8577 if(m->isOptional) {
8578 if(m->isArray)
8579 ptr += sizeof(size_t);
8580 if(*(void* const*)ptr != NULL)
8581 encodingMask |= (UA_UInt32) 1 << optFieldCounter;
8582 ptr += sizeof(void *);
8583 optFieldCounter++;
8584 } else if (m->isArray) {
8585 ptr += sizeof(size_t);
8586 ptr += sizeof(void *);
8587 } else {
8588 ptr += mt->memSize;
8589 }
8590 }
8591
8592 /* Encode the mask */
8593 status ret = ENCODE_DIRECT(&encodingMask, UInt32);
8594 UA_CHECK_STATUS(ret, ctx->depth--; return ret);
8595
8596 /* Loop over members */
8597 ptr = (uintptr_t)src;
8598 for(size_t i = 0, o = 0; i < type->membersSize && UA_LIKELY(ret == UA_STATUSCODE_GOOD); ++i) {
8599 const UA_DataTypeMember *m = &type->members[i];
8600 const UA_DataType *mt = m->memberType;
8601 ptr += m->padding;
8602
8603 if(m->isOptional) {
8604 if(!(encodingMask & (UA_UInt32) ( (UA_UInt32) 1<<(o++)))) {
8605 /* Optional and not contained */
8606 if(m->isArray)
8607 ptr += sizeof(size_t);
8608 } else if(m->isArray) {
8609 /* Optional Array */
8610 const size_t length = *((const size_t *) ptr);
8611 ptr += sizeof(size_t);
8612 ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *) ptr, length, type: mt, ctx);
8613 } else {
8614 /* Optional Scalar */
8615 ret = encodeWithExchangeBuffer(ptr: *(void* const*) ptr, type: mt, ctx);
8616 }
8617 ptr += sizeof(void *);
8618 continue;
8619 }
8620
8621 /* Mandatory Array */
8622 if(m->isArray) {
8623 const size_t length = *((const size_t *) ptr);
8624 ptr += sizeof(size_t);
8625 ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *) ptr, length, type: mt, ctx);
8626 ptr += sizeof(void *);
8627 continue;
8628 }
8629
8630 /* Mandatory Scalar */
8631 ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx);
8632 ptr += mt->memSize;
8633 }
8634 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8635
8636 ctx->depth--;
8637 return ret;
8638}
8639
8640static status
8641encodeBinaryUnion(const void *src, const UA_DataType *type, Ctx *ctx) {
8642 /* Check the recursion limit */
8643 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8644 return UA_STATUSCODE_BADENCODINGERROR);
8645 ctx->depth++;
8646
8647 /* Encode the selection */
8648 const UA_UInt32 selection = *(const UA_UInt32*)src;
8649 status ret = ENCODE_DIRECT(&selection, UInt32);
8650 if(UA_UNLIKELY(ret != UA_STATUSCODE_GOOD) || selection == 0) {
8651 ctx->depth--;
8652 return ret;
8653 }
8654
8655 /* Select the member */
8656 const UA_DataTypeMember *m = &type->members[selection-1];
8657 const UA_DataType *mt = m->memberType;
8658
8659 /* Encode the member */
8660 uintptr_t ptr = ((uintptr_t)src) + m->padding; /* includes the switchfield length */
8661 if(!m->isArray) {
8662 ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx);
8663 } else {
8664 const size_t length = *((const size_t*)ptr);
8665 ptr += sizeof(size_t);
8666 ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt, ctx);
8667 }
8668
8669 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8670
8671 ctx->depth--;
8672 return ret;
8673}
8674
8675static status
8676encodeBinaryNotImplemented(const void *src, const UA_DataType *type, Ctx *ctx) {
8677 (void)src, (void)type, (void)ctx;
8678 return UA_STATUSCODE_BADNOTIMPLEMENTED;
8679}
8680
8681const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS] = {
8682 (encodeBinarySignature)Boolean_encodeBinary,
8683 (encodeBinarySignature)Byte_encodeBinary, /* SByte */
8684 (encodeBinarySignature)Byte_encodeBinary,
8685 (encodeBinarySignature)UInt16_encodeBinary, /* Int16 */
8686 (encodeBinarySignature)UInt16_encodeBinary,
8687 (encodeBinarySignature)UInt32_encodeBinary, /* Int32 */
8688 (encodeBinarySignature)UInt32_encodeBinary,
8689 (encodeBinarySignature)UInt64_encodeBinary, /* Int64 */
8690 (encodeBinarySignature)UInt64_encodeBinary,
8691 (encodeBinarySignature)Float_encodeBinary,
8692 (encodeBinarySignature)Double_encodeBinary,
8693 (encodeBinarySignature)String_encodeBinary,
8694 (encodeBinarySignature)UInt64_encodeBinary, /* DateTime */
8695 (encodeBinarySignature)Guid_encodeBinary,
8696 (encodeBinarySignature)String_encodeBinary, /* ByteString */
8697 (encodeBinarySignature)String_encodeBinary, /* XmlElement */
8698 (encodeBinarySignature)NodeId_encodeBinary,
8699 (encodeBinarySignature)ExpandedNodeId_encodeBinary,
8700 (encodeBinarySignature)UInt32_encodeBinary, /* StatusCode */
8701 (encodeBinarySignature)QualifiedName_encodeBinary,
8702 (encodeBinarySignature)LocalizedText_encodeBinary,
8703 (encodeBinarySignature)ExtensionObject_encodeBinary,
8704 (encodeBinarySignature)DataValue_encodeBinary,
8705 (encodeBinarySignature)Variant_encodeBinary,
8706 (encodeBinarySignature)DiagnosticInfo_encodeBinary,
8707 (encodeBinarySignature)encodeBinaryNotImplemented, /* Decimal */
8708 (encodeBinarySignature)UInt32_encodeBinary, /* Enumeration */
8709 (encodeBinarySignature)encodeBinaryStruct,
8710 (encodeBinarySignature)encodeBinaryStructWithOptFields, /* Structure with Optional Fields */
8711 (encodeBinarySignature)encodeBinaryUnion, /* Union */
8712 (encodeBinarySignature)encodeBinaryStruct /* BitfieldCluster */
8713};
8714
8715status
8716UA_encodeBinaryInternal(const void *src, const UA_DataType *type,
8717 u8 **bufPos, const u8 **bufEnd,
8718 UA_exchangeEncodeBuffer exchangeCallback,
8719 void *exchangeHandle) {
8720 /* Set up the context */
8721 Ctx ctx;
8722 ctx.pos = *bufPos;
8723 ctx.end = *bufEnd;
8724 ctx.depth = 0;
8725 ctx.exchangeBufferCallback = exchangeCallback;
8726 ctx.exchangeBufferCallbackHandle = exchangeHandle;
8727
8728 UA_CHECK_MEM(ctx.pos, return UA_STATUSCODE_BADINVALIDARGUMENT);
8729
8730 /* Encode */
8731 status ret = encodeWithExchangeBuffer(ptr: src, type, ctx: &ctx);
8732 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8733
8734 /* Set the new buffer position for the output. Beware that the buffer might
8735 * have been exchanged internally. */
8736 *bufPos = ctx.pos;
8737 *bufEnd = ctx.end;
8738 return ret;
8739}
8740
8741UA_StatusCode
8742UA_encodeBinary(const void *p, const UA_DataType *type,
8743 UA_ByteString *outBuf) {
8744 /* Allocate buffer */
8745 UA_Boolean allocated = false;
8746 status res = UA_STATUSCODE_GOOD;
8747 if(outBuf->length == 0) {
8748 size_t len = UA_calcSizeBinary(p, type);
8749 res = UA_ByteString_allocBuffer(bs: outBuf, length: len);
8750 if(res != UA_STATUSCODE_GOOD)
8751 return res;
8752 allocated = true;
8753 }
8754
8755 /* Encode */
8756 u8 *pos = outBuf->data;
8757 const u8 *posEnd = &outBuf->data[outBuf->length];
8758 res = UA_encodeBinaryInternal(src: p, type, bufPos: &pos, bufEnd: &posEnd, NULL, NULL);
8759
8760 /* Clean up */
8761 if(res == UA_STATUSCODE_GOOD) {
8762 outBuf->length = (size_t)((uintptr_t)pos - (uintptr_t)outBuf->data);
8763 } else if(allocated) {
8764 UA_ByteString_clear(p: outBuf);
8765 }
8766 return res;
8767}
8768
8769static status
8770decodeBinaryNotImplemented(void *dst, const UA_DataType *type, Ctx *ctx) {
8771 (void)dst, (void)type, (void)ctx;
8772 return UA_STATUSCODE_BADNOTIMPLEMENTED;
8773}
8774
8775static status
8776decodeBinaryStructure(void *dst, const UA_DataType *type, Ctx *ctx) {
8777 /* Check the recursion limit */
8778 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8779 return UA_STATUSCODE_BADENCODINGERROR);
8780 ctx->depth++;
8781
8782 uintptr_t ptr = (uintptr_t)dst;
8783 status ret = UA_STATUSCODE_GOOD;
8784 u8 membersSize = type->membersSize;
8785
8786 /* Loop over members */
8787 for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
8788 const UA_DataTypeMember *m = &type->members[i];
8789 const UA_DataType *mt = m->memberType;
8790 ptr += m->padding;
8791
8792 /* Array */
8793 if(m->isArray) {
8794 size_t *length = (size_t*)ptr;
8795 ptr += sizeof(size_t);
8796 ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt , ctx);
8797 ptr += sizeof(void*);
8798 continue;
8799 }
8800
8801 /* Scalar */
8802 ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
8803 ptr += mt->memSize;
8804 }
8805
8806 ctx->depth--;
8807 return ret;
8808}
8809
8810static status
8811decodeBinaryStructureWithOptFields(void *dst, const UA_DataType *type, Ctx *ctx) {
8812 /* Check the recursion limit */
8813 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
8814 ctx->depth++;
8815
8816 uintptr_t ptr = (uintptr_t)dst;
8817 UA_UInt32 encodingMask = 0;
8818 status ret = UInt32_decodeBinary(dst: &encodingMask, type: &UA_TYPES[UA_TYPES_UINT32], ctx);
8819 UA_CHECK_STATUS(ret, ctx->depth--; return ret);
8820
8821 /* Loop over members */
8822 for(size_t i = 0, o = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
8823 const UA_DataTypeMember *m = &type->members[i];
8824 const UA_DataType *mt = m->memberType;
8825 ptr += m->padding;
8826 if(m->isOptional) {
8827 if(!(encodingMask & (UA_UInt32) ( (UA_UInt32) 1<<(o++)))) {
8828 /* Optional field is not contained */
8829 if(m->isArray)
8830 ptr += sizeof(size_t);
8831 } else if(m->isArray) {
8832 /* Optional Array */
8833 size_t *length = (size_t*)ptr;
8834 ptr += sizeof(size_t);
8835 ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt , ctx);
8836 } else {
8837 /* Optional Scalar */
8838 *(void *UA_RESTRICT *UA_RESTRICT) ptr = UA_calloc(nmemb: 1, size: mt->memSize);
8839 UA_CHECK_MEM(*(void *UA_RESTRICT *UA_RESTRICT) ptr, return UA_STATUSCODE_BADOUTOFMEMORY);
8840 ret = decodeBinaryJumpTable[mt->typeKind](*(void *UA_RESTRICT *UA_RESTRICT) ptr, mt, ctx);
8841 }
8842 ptr += sizeof(void *);
8843 continue;
8844 }
8845
8846 /* Array */
8847 if(m->isArray) {
8848 size_t *length = (size_t *)ptr;
8849 ptr += sizeof(size_t);
8850 ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt, ctx);
8851 ptr += sizeof(void *);
8852 continue;
8853 }
8854
8855 /* Scalar */
8856 ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
8857 ptr += mt->memSize;
8858 }
8859 ctx->depth--;
8860 return ret;
8861}
8862
8863static status
8864decodeBinaryUnion(void *UA_RESTRICT dst, const UA_DataType *type, Ctx *ctx) {
8865 /* Check the recursion limit */
8866 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8867 return UA_STATUSCODE_BADENCODINGERROR);
8868
8869 /* Decode the selection directly into the switchfield */
8870 status ret = DECODE_DIRECT(dst, UInt32);
8871 UA_CHECK_STATUS(ret, return ret);
8872
8873 /* No content? */
8874 UA_UInt32 selection = *(UA_UInt32*)dst;
8875 if(selection == 0)
8876 return UA_STATUSCODE_GOOD;
8877
8878 /* Sanity check the selection */
8879 UA_CHECK(selection-1 < type->membersSize,
8880 return UA_STATUSCODE_BADDECODINGERROR);
8881
8882 /* Select the member */
8883 const UA_DataTypeMember *m = &type->members[selection-1];
8884 const UA_DataType *mt = m->memberType;
8885
8886 /* Decode */
8887 ctx->depth++;
8888 uintptr_t ptr = ((uintptr_t)dst) + m->padding; /* includes the switchfield */
8889 if(!m->isArray) {
8890 ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
8891 } else {
8892 size_t *length = (size_t *)ptr;
8893 ptr += sizeof(size_t);
8894 ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt, ctx);
8895 }
8896 ctx->depth--;
8897 return ret;
8898}
8899
8900const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS] = {
8901 (decodeBinarySignature)Boolean_decodeBinary,
8902 (decodeBinarySignature)Byte_decodeBinary, /* SByte */
8903 (decodeBinarySignature)Byte_decodeBinary,
8904 (decodeBinarySignature)UInt16_decodeBinary, /* Int16 */
8905 (decodeBinarySignature)UInt16_decodeBinary,
8906 (decodeBinarySignature)UInt32_decodeBinary, /* Int32 */
8907 (decodeBinarySignature)UInt32_decodeBinary,
8908 (decodeBinarySignature)UInt64_decodeBinary, /* Int64 */
8909 (decodeBinarySignature)UInt64_decodeBinary,
8910 (decodeBinarySignature)Float_decodeBinary,
8911 (decodeBinarySignature)Double_decodeBinary,
8912 (decodeBinarySignature)String_decodeBinary,
8913 (decodeBinarySignature)UInt64_decodeBinary, /* DateTime */
8914 (decodeBinarySignature)Guid_decodeBinary,
8915 (decodeBinarySignature)String_decodeBinary, /* ByteString */
8916 (decodeBinarySignature)String_decodeBinary, /* XmlElement */
8917 (decodeBinarySignature)NodeId_decodeBinary,
8918 (decodeBinarySignature)ExpandedNodeId_decodeBinary,
8919 (decodeBinarySignature)UInt32_decodeBinary, /* StatusCode */
8920 (decodeBinarySignature)QualifiedName_decodeBinary,
8921 (decodeBinarySignature)LocalizedText_decodeBinary,
8922 (decodeBinarySignature)ExtensionObject_decodeBinary,
8923 (decodeBinarySignature)DataValue_decodeBinary,
8924 (decodeBinarySignature)Variant_decodeBinary,
8925 (decodeBinarySignature)DiagnosticInfo_decodeBinary,
8926 (decodeBinarySignature)decodeBinaryNotImplemented, /* Decimal */
8927 (decodeBinarySignature)UInt32_decodeBinary, /* Enumeration */
8928 (decodeBinarySignature)decodeBinaryStructure,
8929 (decodeBinarySignature)decodeBinaryStructureWithOptFields, /* Structure with optional fields */
8930 (decodeBinarySignature)decodeBinaryUnion, /* Union */
8931 (decodeBinarySignature)decodeBinaryNotImplemented /* BitfieldCluster */
8932};
8933
8934status
8935UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
8936 void *dst, const UA_DataType *type,
8937 const UA_DataTypeArray *customTypes) {
8938 /* Set up the context */
8939 Ctx ctx;
8940 ctx.pos = &src->data[*offset];
8941 ctx.end = &src->data[src->length];
8942 ctx.depth = 0;
8943 ctx.customTypes = customTypes;
8944
8945 /* Decode */
8946 memset(s: dst, c: 0, n: type->memSize); /* Initialize the value */
8947 status ret = decodeBinaryJumpTable[type->typeKind](dst, type, &ctx);
8948
8949 if(UA_LIKELY(ret == UA_STATUSCODE_GOOD)) {
8950 /* Set the new offset */
8951 *offset = (size_t)(ctx.pos - src->data) / sizeof(u8);
8952 } else {
8953 /* Clean up */
8954 UA_clear(p: dst, type);
8955 memset(s: dst, c: 0, n: type->memSize);
8956 }
8957 return ret;
8958}
8959
8960UA_StatusCode
8961UA_decodeBinary(const UA_ByteString *inBuf,
8962 void *p, const UA_DataType *type,
8963 const UA_DecodeBinaryOptions *options) {
8964 size_t offset = 0;
8965 const UA_DataTypeArray *customTypes = options ? options->customTypes : NULL;
8966 return UA_decodeBinaryInternal(src: inBuf, offset: &offset, dst: p, type, customTypes);
8967}
8968
8969/**
8970 * Compute the Message Size
8971 * ------------------------
8972 * The following methods are used to compute the length of a datum in binary
8973 * encoding. */
8974
8975static size_t
8976Array_calcSizeBinary(const void *src, size_t length, const UA_DataType *type) {
8977 size_t s = 4; /* length */
8978 if(type->overlayable) {
8979 s += type->memSize * length;
8980 return s;
8981 }
8982 uintptr_t ptr = (uintptr_t)src;
8983 for(size_t i = 0; i < length; ++i) {
8984 s += calcSizeBinaryJumpTable[type->typeKind]((const void*)ptr, type);
8985 ptr += type->memSize;
8986 }
8987 return s;
8988}
8989
8990static size_t calcSizeBinary1(const void *_, const UA_DataType *__) { (void)_, (void)__; return 1; }
8991static size_t calcSizeBinary2(const void *_, const UA_DataType *__) { (void)_, (void)__; return 2; }
8992static size_t calcSizeBinary4(const void *_, const UA_DataType *__) { (void)_, (void)__; return 4; }
8993static size_t calcSizeBinary8(const void *_, const UA_DataType *__) { (void)_, (void)__; return 8; }
8994
8995CALCSIZE_BINARY(String) { return 4 + src->length; }
8996
8997CALCSIZE_BINARY(Guid) { return 16; }
8998
8999CALCSIZE_BINARY(NodeId) {
9000 size_t s = 1; /* Encoding byte */
9001 switch(src->identifierType) {
9002 case UA_NODEIDTYPE_NUMERIC:
9003 if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
9004 s += 6;
9005 } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
9006 s += 3;
9007 } else {
9008 s += 1;
9009 }
9010 break;
9011 case UA_NODEIDTYPE_BYTESTRING:
9012 case UA_NODEIDTYPE_STRING:
9013 s += 2;
9014 s += String_calcSizeBinary(src: &src->identifier.string, NULL);
9015 break;
9016 case UA_NODEIDTYPE_GUID:
9017 s += 18;
9018 break;
9019 default:
9020 return 0;
9021 }
9022 return s;
9023}
9024
9025CALCSIZE_BINARY(ExpandedNodeId) {
9026 size_t s = NodeId_calcSizeBinary(src: &src->nodeId, NULL);
9027 if(src->namespaceUri.length > 0)
9028 s += String_calcSizeBinary(src: &src->namespaceUri, NULL);
9029 if(src->serverIndex > 0)
9030 s += 4;
9031 return s;
9032}
9033
9034CALCSIZE_BINARY(QualifiedName) {
9035 return 2 + String_calcSizeBinary(src: &src->name, NULL);
9036}
9037
9038CALCSIZE_BINARY(LocalizedText) {
9039 size_t s = 1; /* Encoding byte */
9040 if(src->locale.data)
9041 s += String_calcSizeBinary(src: &src->locale, NULL);
9042 if(src->text.data)
9043 s += String_calcSizeBinary(src: &src->text, NULL);
9044 return s;
9045}
9046
9047CALCSIZE_BINARY(ExtensionObject) {
9048 size_t s = 1; /* Encoding byte */
9049
9050 /* Encoded content */
9051 if(src->encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
9052 s += NodeId_calcSizeBinary(src: &src->content.encoded.typeId, NULL);
9053 switch(src->encoding) {
9054 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
9055 break;
9056 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
9057 case UA_EXTENSIONOBJECT_ENCODED_XML:
9058 s += String_calcSizeBinary(src: &src->content.encoded.body, NULL);
9059 break;
9060 default:
9061 return 0;
9062 }
9063 return s;
9064 }
9065
9066 /* Decoded content */
9067 if(!src->content.decoded.type || !src->content.decoded.data)
9068 return 0;
9069 if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
9070 return 0;
9071
9072 s += NodeId_calcSizeBinary(src: &src->content.decoded.type->binaryEncodingId, NULL); /* Type encoding length */
9073 s += 4; /* Encoding length field */
9074 const UA_DataType *type = src->content.decoded.type;
9075 s += calcSizeBinaryJumpTable[type->typeKind](src->content.decoded.data, type); /* Encoding length */
9076 return s;
9077}
9078
9079CALCSIZE_BINARY(Variant) {
9080 size_t s = 1; /* Encoding byte */
9081 if(!src->type)
9082 return s;
9083
9084 const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
9085 if(isArray)
9086 s += Array_calcSizeBinary(src: src->data, length: src->arrayLength, type: src->type);
9087 else
9088 s += calcSizeBinaryJumpTable[src->type->typeKind](src->data, src->type);
9089
9090 const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO);
9091 const UA_Boolean isEnum = (src->type->typeKind == UA_DATATYPEKIND_ENUM);
9092 if(!isBuiltin && !isEnum) {
9093 /* The type is wrapped inside an extensionobject */
9094 /* (NodeId + encoding byte + extension object length) * array length */
9095 size_t length = isArray ? src->arrayLength : 1;
9096 s += (NodeId_calcSizeBinary(src: &src->type->binaryEncodingId, NULL) + 1 + 4) * length;
9097 }
9098
9099 const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
9100 if(hasDimensions)
9101 s += Array_calcSizeBinary(src: src->arrayDimensions, length: src->arrayDimensionsSize,
9102 type: &UA_TYPES[UA_TYPES_INT32]);
9103 return s;
9104}
9105
9106CALCSIZE_BINARY(DataValue) {
9107 size_t s = 1; /* Encoding byte */
9108 if(src->hasValue)
9109 s += Variant_calcSizeBinary(src: &src->value, NULL);
9110 if(src->hasStatus)
9111 s += 4;
9112 if(src->hasSourceTimestamp)
9113 s += 8;
9114 if(src->hasSourcePicoseconds)
9115 s += 2;
9116 if(src->hasServerTimestamp)
9117 s += 8;
9118 if(src->hasServerPicoseconds)
9119 s += 2;
9120 return s;
9121}
9122
9123CALCSIZE_BINARY(DiagnosticInfo) {
9124 size_t s = 1; /* Encoding byte */
9125 if(src->hasSymbolicId)
9126 s += 4;
9127 if(src->hasNamespaceUri)
9128 s += 4;
9129 if(src->hasLocalizedText)
9130 s += 4;
9131 if(src->hasLocale)
9132 s += 4;
9133 if(src->hasAdditionalInfo)
9134 s += String_calcSizeBinary(src: &src->additionalInfo, NULL);
9135 if(src->hasInnerStatusCode)
9136 s += 4;
9137 if(src->hasInnerDiagnosticInfo)
9138 s += DiagnosticInfo_calcSizeBinary(src: src->innerDiagnosticInfo, NULL);
9139 return s;
9140}
9141
9142static size_t
9143calcSizeBinaryStructure(const void *p, const UA_DataType *type) {
9144 size_t s = 0;
9145 uintptr_t ptr = (uintptr_t)p;
9146 u8 membersSize = type->membersSize;
9147
9148 /* Loop over members */
9149 for(size_t i = 0; i < membersSize; ++i) {
9150 const UA_DataTypeMember *member = &type->members[i];
9151 const UA_DataType *membertype = member->memberType;
9152 ptr += member->padding;
9153
9154 /* Array */
9155 if(member->isArray) {
9156 const size_t length = *((const size_t*)ptr);
9157 ptr += sizeof(size_t);
9158 s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: membertype);
9159 ptr += sizeof(void*);
9160 continue;
9161 }
9162
9163 /* Scalar */
9164 s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype);
9165 ptr += membertype->memSize;
9166 }
9167
9168 return s;
9169}
9170
9171static size_t
9172calcSizeBinaryStructureWithOptFields(const void *p, const UA_DataType *type) {
9173 /* Start with the size of the encoding mask */
9174 size_t s = sizeof(UA_UInt32);
9175
9176 /* Loop over members */
9177 uintptr_t ptr = (uintptr_t)p;
9178 for(size_t i = 0; i < type->membersSize; ++i) {
9179 const UA_DataTypeMember *member = &type->members[i];
9180 const UA_DataType *membertype = member->memberType;
9181 ptr += member->padding;
9182 if(member->isOptional) {
9183 if((member->isArray && ((*(void* const*)(ptr+sizeof(size_t))) == NULL)) ||
9184 (!member->isArray && (*(void* const*)ptr == NULL))) {
9185 /* Optional member not contained */
9186 if(member->isArray)
9187 ptr += sizeof(size_t);
9188 ptr += sizeof(void *);
9189 continue;
9190 }
9191 /* Fallthrough to take the size into account */
9192 }
9193 /* Array */
9194 if(member->isArray) {
9195 const size_t length = *((const size_t*)ptr);
9196 ptr += sizeof(size_t);
9197 s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: membertype);
9198 ptr += sizeof(void*);
9199 continue;
9200 }
9201 /* Scalar */
9202 if (member->isOptional) {
9203 s += calcSizeBinaryJumpTable[membertype->typeKind](*(void* const*)ptr, membertype);
9204 ptr += sizeof(void *);
9205 } else {
9206 s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype);
9207 ptr += membertype->memSize;
9208 }
9209 }
9210 return s;
9211}
9212
9213static size_t
9214calcSizeBinaryUnion(const void *p, const UA_DataType *type) {
9215 size_t s = 4; /* UA_TYPES[UA_TYPES_UINT32].memSize; */
9216 const UA_UInt32 selection = *(const UA_UInt32 *)p;
9217 if(selection == 0)
9218 return s;
9219
9220 const UA_DataTypeMember *m = &type->members[selection-1];
9221 const UA_DataType *mt = m->memberType;
9222
9223 uintptr_t ptr = ((uintptr_t)p) + m->padding; /* includes switchfield length */
9224 if(!m->isArray) {
9225 s += UA_calcSizeBinary(p: (const void*)ptr, type: mt);
9226 } else {
9227 const size_t length = *((const size_t*)ptr);
9228 ptr += sizeof(size_t);
9229 s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt);
9230 }
9231 return s;
9232}
9233
9234static size_t
9235calcSizeBinaryNotImplemented(const void *p, const UA_DataType *type) {
9236 (void)p, (void)type;
9237 return 0;
9238}
9239
9240const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS] = {
9241 (calcSizeBinarySignature)calcSizeBinary1, /* Boolean */
9242 (calcSizeBinarySignature)calcSizeBinary1, /* SByte */
9243 (calcSizeBinarySignature)calcSizeBinary1, /* Byte */
9244 (calcSizeBinarySignature)calcSizeBinary2, /* Int16 */
9245 (calcSizeBinarySignature)calcSizeBinary2, /* UInt16 */
9246 (calcSizeBinarySignature)calcSizeBinary4, /* Int32 */
9247 (calcSizeBinarySignature)calcSizeBinary4, /* UInt32 */
9248 (calcSizeBinarySignature)calcSizeBinary8, /* Int64 */
9249 (calcSizeBinarySignature)calcSizeBinary8, /* UInt64 */
9250 (calcSizeBinarySignature)calcSizeBinary4, /* Float */
9251 (calcSizeBinarySignature)calcSizeBinary8, /* Double */
9252 (calcSizeBinarySignature)String_calcSizeBinary,
9253 (calcSizeBinarySignature)calcSizeBinary8, /* DateTime */
9254 (calcSizeBinarySignature)Guid_calcSizeBinary,
9255 (calcSizeBinarySignature)String_calcSizeBinary, /* ByteString */
9256 (calcSizeBinarySignature)String_calcSizeBinary, /* XmlElement */
9257 (calcSizeBinarySignature)NodeId_calcSizeBinary,
9258 (calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary,
9259 (calcSizeBinarySignature)calcSizeBinary4, /* StatusCode */
9260 (calcSizeBinarySignature)QualifiedName_calcSizeBinary,
9261 (calcSizeBinarySignature)LocalizedText_calcSizeBinary,
9262 (calcSizeBinarySignature)ExtensionObject_calcSizeBinary,
9263 (calcSizeBinarySignature)DataValue_calcSizeBinary,
9264 (calcSizeBinarySignature)Variant_calcSizeBinary,
9265 (calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary,
9266 (calcSizeBinarySignature)calcSizeBinaryNotImplemented, /* Decimal */
9267 (calcSizeBinarySignature)calcSizeBinary4, /* Enumeration */
9268 (calcSizeBinarySignature)calcSizeBinaryStructure,
9269 (calcSizeBinarySignature)calcSizeBinaryStructureWithOptFields, /* Structure with Optional Fields */
9270 (calcSizeBinarySignature)calcSizeBinaryUnion, /* Union */
9271 (calcSizeBinarySignature)calcSizeBinaryNotImplemented /* BitfieldCluster */
9272};
9273
9274size_t
9275UA_calcSizeBinary(const void *p, const UA_DataType *type) {
9276 return calcSizeBinaryJumpTable[type->typeKind](p, type);
9277}
9278
9279/**** amalgamated original file "/src/ua_types_print.c" ****/
9280
9281/* This Source Code Form is subject to the terms of the Mozilla Public
9282 * License, v. 2.0. If a copy of the MPL was not distributed with this
9283 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9284 *
9285 * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
9286 */
9287
9288
9289
9290/* Printing of NodeIds is always enabled. We need it for logging. */
9291
9292UA_StatusCode
9293UA_NodeId_print(const UA_NodeId *id, UA_String *output) {
9294 UA_String_clear(p: output);
9295 if(!id)
9296 return UA_STATUSCODE_GOOD;
9297
9298 char *nsStr = NULL;
9299 long snprintfLen = 0;
9300 size_t nsLen = 0;
9301 if(id->namespaceIndex != 0) {
9302 nsStr = (char*)UA_malloc(size: 9+1); // strlen("ns=XXXXX;") = 9 + Nullbyte
9303 if(!nsStr)
9304 return UA_STATUSCODE_BADOUTOFMEMORY;
9305 snprintfLen = UA_snprintf(s: nsStr, maxlen: 10, format: "ns=%d;", id->namespaceIndex);
9306 if(snprintfLen < 0 || snprintfLen >= 10) {
9307 UA_free(ptr: nsStr);
9308 return UA_STATUSCODE_BADINTERNALERROR;
9309 }
9310 nsLen = (size_t)(snprintfLen);
9311 }
9312
9313 UA_ByteString byteStr = UA_BYTESTRING_NULL;
9314 switch (id->identifierType) {
9315 case UA_NODEIDTYPE_NUMERIC:
9316 /* ns (2 byte, 65535) = 5 chars, numeric (4 byte, 4294967295) = 10
9317 * chars, delim = 1 , nullbyte = 1-> 17 chars */
9318 output->length = nsLen + 2 + 10 + 1;
9319 output->data = (UA_Byte*)UA_malloc(size: output->length);
9320 if(output->data == NULL) {
9321 output->length = 0;
9322 UA_free(ptr: nsStr);
9323 return UA_STATUSCODE_BADOUTOFMEMORY;
9324 }
9325 snprintfLen = UA_snprintf(s: (char*)output->data, maxlen: output->length, format: "%si=%lu",
9326 nsLen > 0 ? nsStr : "",
9327 (unsigned long )id->identifier.numeric);
9328 break;
9329 case UA_NODEIDTYPE_STRING:
9330 /* ns (16bit) = 5 chars, strlen + nullbyte */
9331 output->length = nsLen + 2 + id->identifier.string.length + 1;
9332 output->data = (UA_Byte*)UA_malloc(size: output->length);
9333 if(output->data == NULL) {
9334 output->length = 0;
9335 UA_free(ptr: nsStr);
9336 return UA_STATUSCODE_BADOUTOFMEMORY;
9337 }
9338 snprintfLen = UA_snprintf(s: (char*)output->data, maxlen: output->length, format: "%ss=%.*s",
9339 nsLen > 0 ? nsStr : "", (int)id->identifier.string.length,
9340 id->identifier.string.data);
9341 break;
9342 case UA_NODEIDTYPE_GUID:
9343 /* ns (16bit) = 5 chars + strlen(A123456C-0ABC-1A2B-815F-687212AAEE1B)=36 + nullbyte */
9344 output->length = nsLen + 2 + 36 + 1;
9345 output->data = (UA_Byte*)UA_malloc(size: output->length);
9346 if(output->data == NULL) {
9347 output->length = 0;
9348 UA_free(ptr: nsStr);
9349 return UA_STATUSCODE_BADOUTOFMEMORY;
9350 }
9351 snprintfLen = UA_snprintf(s: (char*)output->data, maxlen: output->length,
9352 format: "%sg=" UA_PRINTF_GUID_FORMAT, nsLen > 0 ? nsStr : "",
9353 UA_PRINTF_GUID_DATA(id->identifier.guid));
9354 break;
9355 case UA_NODEIDTYPE_BYTESTRING:
9356 UA_ByteString_toBase64(bs: &id->identifier.byteString, output: &byteStr);
9357 /* ns (16bit) = 5 chars + LEN + nullbyte */
9358 output->length = nsLen + 2 + byteStr.length + 1;
9359 output->data = (UA_Byte*)UA_malloc(size: output->length);
9360 if(output->data == NULL) {
9361 output->length = 0;
9362 UA_String_clear(p: &byteStr);
9363 UA_free(ptr: nsStr);
9364 return UA_STATUSCODE_BADOUTOFMEMORY;
9365 }
9366 snprintfLen = UA_snprintf(s: (char*)output->data, maxlen: output->length, format: "%sb=%.*s",
9367 nsLen > 0 ? nsStr : "",
9368 (int)byteStr.length, byteStr.data);
9369 UA_String_clear(p: &byteStr);
9370 break;
9371 }
9372 UA_free(ptr: nsStr);
9373
9374 if(snprintfLen < 0 || snprintfLen >= (long) output->length) {
9375 UA_free(ptr: output->data);
9376 output->data = NULL;
9377 output->length = 0;
9378 return UA_STATUSCODE_BADINTERNALERROR;
9379 }
9380 output->length = (size_t)snprintfLen;
9381
9382 return UA_STATUSCODE_GOOD;
9383}
9384
9385UA_StatusCode
9386UA_ExpandedNodeId_print(const UA_ExpandedNodeId *id, UA_String *output) {
9387 /* Don't print the namespace-index if a NamespaceUri is set */
9388 UA_NodeId nid = id->nodeId;
9389 if(id->namespaceUri.data != NULL)
9390 nid.namespaceIndex = 0;
9391
9392 /* Encode the NodeId */
9393 UA_String outNid = UA_STRING_NULL;
9394 UA_StatusCode res = UA_NodeId_print(id: &nid, output: &outNid);
9395 if(res != UA_STATUSCODE_GOOD)
9396 return res;
9397
9398 /* Encode the ServerIndex */
9399 char svr[100];
9400 if(id->serverIndex == 0)
9401 svr[0] = 0;
9402 else
9403 UA_snprintf(s: svr, maxlen: 100, format: "svr=%"PRIu32";", id->serverIndex);
9404 size_t svrlen = strlen(s: svr);
9405
9406 /* Encode the NamespaceUri */
9407 char nsu[100];
9408 if(id->namespaceUri.data == NULL)
9409 nsu[0] = 0;
9410 else
9411 UA_snprintf(s: nsu, maxlen: 100, format: "nsu=%.*s;", (int)id->namespaceUri.length, id->namespaceUri.data);
9412 size_t nsulen = strlen(s: nsu);
9413
9414 /* Combine everything */
9415 res = UA_ByteString_allocBuffer(bs: (UA_String*)output, length: outNid.length + svrlen + nsulen);
9416 if(res == UA_STATUSCODE_GOOD) {
9417 memcpy(dest: output->data, src: svr, n: svrlen);
9418 memcpy(dest: &output->data[svrlen], src: nsu, n: nsulen);
9419 memcpy(dest: &output->data[svrlen+nsulen], src: outNid.data, n: outNid.length);
9420 }
9421
9422 UA_String_clear(p: &outNid);
9423 return res;
9424}
9425
9426#ifdef UA_ENABLE_TYPEDESCRIPTION
9427
9428/***********************/
9429/* Jumptable Signature */
9430/***********************/
9431
9432typedef struct UA_PrintElement {
9433 TAILQ_ENTRY(UA_PrintElement) next;
9434 size_t length;
9435 UA_Byte data[];
9436} UA_PrintOutput;
9437
9438typedef struct {
9439 size_t depth;
9440 TAILQ_HEAD(, UA_PrintElement) outputs;
9441} UA_PrintContext;
9442
9443typedef UA_StatusCode
9444(*UA_printSignature)(UA_PrintContext *ctx, const void *p,
9445 const UA_DataType *type);
9446
9447extern const UA_printSignature printJumpTable[UA_DATATYPEKINDS];
9448
9449/********************/
9450/* Helper Functions */
9451/********************/
9452
9453static UA_PrintOutput *
9454UA_PrintContext_addOutput(UA_PrintContext *ctx, size_t length) {
9455 /* Protect against overlong output in pretty-printing */
9456 if(length > 2<<16)
9457 return NULL;
9458 UA_PrintOutput *output = (UA_PrintOutput*)UA_malloc(size: sizeof(UA_PrintOutput) + length + 1);
9459 if(!output)
9460 return NULL;
9461 output->length = length;
9462 TAILQ_INSERT_TAIL(&ctx->outputs, output, next);
9463 return output;
9464}
9465
9466static UA_StatusCode
9467UA_PrintContext_addNewlineTabs(UA_PrintContext *ctx, size_t tabs) {
9468 UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, length: tabs+1);
9469 if(!out)
9470 return UA_STATUSCODE_BADOUTOFMEMORY;
9471 out->data[0] = '\n';
9472 for(size_t i = 1; i <= tabs; i++)
9473 out->data[i] = '\t';
9474 return UA_STATUSCODE_GOOD;
9475}
9476
9477static UA_StatusCode
9478UA_PrintContext_addName(UA_PrintContext *ctx, const char *name) {
9479 size_t nameLen = strlen(s: name);
9480 UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, length: nameLen+2);
9481 if(!out)
9482 return UA_STATUSCODE_BADOUTOFMEMORY;
9483 memcpy(dest: &out->data, src: name, n: nameLen);
9484 out->data[nameLen] = ':';
9485 out->data[nameLen+1] = ' ';
9486 return UA_STATUSCODE_GOOD;
9487}
9488
9489static UA_StatusCode
9490UA_PrintContext_addString(UA_PrintContext *ctx, const char *str) {
9491 size_t len = strlen(s: str);
9492 UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, length: len);
9493 if(!out)
9494 return UA_STATUSCODE_BADOUTOFMEMORY;
9495 memcpy(dest: &out->data, src: str, n: len);
9496 return UA_STATUSCODE_GOOD;
9497}
9498
9499/*********************/
9500/* Printing Routines */
9501/*********************/
9502
9503static UA_StatusCode
9504printArray(UA_PrintContext *ctx, const void *p, const size_t length,
9505 const UA_DataType *type);
9506
9507static UA_StatusCode
9508printBoolean(UA_PrintContext *ctx, const UA_Boolean *p, const UA_DataType *_) {
9509 if(*p)
9510 return UA_PrintContext_addString(ctx, str: "true");
9511 return UA_PrintContext_addString(ctx, str: "false");
9512}
9513
9514static UA_StatusCode
9515printSByte(UA_PrintContext *ctx, const UA_SByte *p, const UA_DataType *_) {
9516 char out[32];
9517 UA_snprintf(s: out, maxlen: 32, format: "%"PRIi8, *p);
9518 return UA_PrintContext_addString(ctx, str: out);
9519}
9520
9521static UA_StatusCode
9522printByte(UA_PrintContext *ctx, const UA_Byte *p, const UA_DataType *_) {
9523 char out[32];
9524 UA_snprintf(s: out, maxlen: 32, format: "%"PRIu8, *p);
9525 return UA_PrintContext_addString(ctx, str: out);
9526}
9527
9528static UA_StatusCode
9529printInt16(UA_PrintContext *ctx, const UA_Int16 *p, const UA_DataType *_) {
9530 char out[32];
9531 UA_snprintf(s: out, maxlen: 32, format: "%"PRIi16, *p);
9532 return UA_PrintContext_addString(ctx, str: out);
9533}
9534
9535static UA_StatusCode
9536printUInt16(UA_PrintContext *ctx, const UA_UInt16 *p, const UA_DataType *_) {
9537 char out[32];
9538 UA_snprintf(s: out, maxlen: 32, format: "%"PRIu16, *p);
9539 return UA_PrintContext_addString(ctx, str: out);
9540}
9541
9542static UA_StatusCode
9543printInt32(UA_PrintContext *ctx, const UA_Int32 *p, const UA_DataType *_) {
9544 char out[32];
9545 UA_snprintf(s: out, maxlen: 32, format: "%"PRIi32, *p);
9546 return UA_PrintContext_addString(ctx, str: out);
9547}
9548
9549static UA_StatusCode
9550printUInt32(UA_PrintContext *ctx, const UA_UInt32 *p, const UA_DataType *_) {
9551 char out[32];
9552 UA_snprintf(s: out, maxlen: 32, format: "%"PRIu32, *p);
9553 return UA_PrintContext_addString(ctx, str: out);
9554}
9555
9556static UA_StatusCode
9557printInt64(UA_PrintContext *ctx, const UA_Int64 *p, const UA_DataType *_) {
9558 char out[64];
9559 UA_snprintf(s: out, maxlen: 64, format: "%"PRIi64, *p);
9560 return UA_PrintContext_addString(ctx, str: out);
9561}
9562
9563static UA_StatusCode
9564printUInt64(UA_PrintContext *ctx, const UA_UInt64 *p, const UA_DataType *_) {
9565 char out[64];
9566 UA_snprintf(s: out, maxlen: 64, format: "%"PRIu64, *p);
9567 return UA_PrintContext_addString(ctx, str: out);
9568}
9569
9570static UA_StatusCode
9571printFloat(UA_PrintContext *ctx, const UA_Float *p, const UA_DataType *_) {
9572 char out[64];
9573 UA_snprintf(s: out, maxlen: 32, format: "%f", *p);
9574 return UA_PrintContext_addString(ctx, str: out);
9575}
9576
9577static UA_StatusCode
9578printDouble(UA_PrintContext *ctx, const UA_Double *p, const UA_DataType *_) {
9579 char out[64];
9580 UA_snprintf(s: out, maxlen: 64, format: "%lf", *p);
9581 return UA_PrintContext_addString(ctx, str: out);
9582}
9583
9584static UA_StatusCode
9585printStatusCode(UA_PrintContext *ctx, const UA_StatusCode *p, const UA_DataType *_) {
9586 return UA_PrintContext_addString(ctx, str: UA_StatusCode_name(code: *p));
9587}
9588
9589static UA_StatusCode
9590printNodeId(UA_PrintContext *ctx, const UA_NodeId *p, const UA_DataType *_) {
9591 UA_String out;
9592 UA_String_init(p: &out);
9593 UA_StatusCode res = UA_NodeId_print(id: p, output: &out);
9594 if(res != UA_STATUSCODE_GOOD)
9595 return res;
9596 UA_PrintOutput *po = UA_PrintContext_addOutput(ctx, length: out.length);
9597 if(po)
9598 memcpy(dest: po->data, src: out.data, n: out.length);
9599 else
9600 res = UA_STATUSCODE_BADOUTOFMEMORY;
9601 UA_String_clear(p: &out);
9602 return res;
9603}
9604
9605static UA_StatusCode
9606printExpandedNodeId(UA_PrintContext *ctx, const UA_ExpandedNodeId *p, const UA_DataType *_) {
9607 UA_String out;
9608 UA_String_init(p: &out);
9609 UA_StatusCode res = UA_ExpandedNodeId_print(id: p, output: &out);
9610 if(res != UA_STATUSCODE_GOOD)
9611 return res;
9612 UA_PrintOutput *po = UA_PrintContext_addOutput(ctx, length: out.length);
9613 if(!po)
9614 return UA_STATUSCODE_BADOUTOFMEMORY;
9615 memcpy(dest: po->data, src: out.data, n: out.length);
9616 UA_String_clear(p: &out);
9617 return UA_STATUSCODE_GOOD;
9618}
9619
9620static UA_StatusCode
9621printDateTime(UA_PrintContext *ctx, const UA_DateTime *p, const UA_DataType *_) {
9622 UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
9623 UA_DateTimeStruct dts = UA_DateTime_toStruct(t: *p);
9624 char dateString[100];
9625 UA_snprintf(s: (char*)dateString, maxlen: 100,
9626 format: "%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)",
9627 dts.year, dts.month, dts.day, dts.hour, dts.min,
9628 dts.sec, dts.milliSec,
9629 (int)(tOffset / UA_DATETIME_SEC / 36));
9630 return UA_PrintContext_addString(ctx, str: dateString);
9631}
9632
9633static UA_StatusCode
9634printGuid(UA_PrintContext *ctx, const UA_Guid *p, const UA_DataType *_) {
9635 char tmp[100];
9636 UA_snprintf(s: tmp, maxlen: 100, UA_PRINTF_GUID_FORMAT, UA_PRINTF_GUID_DATA(*p));
9637 return UA_PrintContext_addString(ctx, str: tmp);
9638}
9639
9640static UA_StatusCode
9641printString(UA_PrintContext *ctx, const UA_String *p, const UA_DataType *_) {
9642 if(!p->data)
9643 return UA_PrintContext_addString(ctx, str: "NullString");
9644 UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, length: p->length+2);
9645 if(!out)
9646 return UA_STATUSCODE_BADOUTOFMEMORY;
9647 UA_snprintf(s: (char*)out->data, maxlen: p->length+3, format: "\"%.*s\"", (int)p->length, p->data);
9648 return UA_STATUSCODE_GOOD;
9649}
9650
9651static UA_StatusCode
9652printByteString(UA_PrintContext *ctx, const UA_ByteString *p, const UA_DataType *_) {
9653 if(!p->data)
9654 return UA_PrintContext_addString(ctx, str: "NullByteString");
9655 UA_String str = UA_BYTESTRING_NULL;
9656 UA_StatusCode res = UA_ByteString_toBase64(bs: p, output: &str);
9657 if(res != UA_STATUSCODE_GOOD)
9658 return res;
9659 res = printString(ctx, p: &str, NULL);
9660 UA_String_clear(p: &str);
9661 return res;
9662}
9663
9664static UA_StatusCode
9665printQualifiedName(UA_PrintContext *ctx, const UA_QualifiedName *p, const UA_DataType *_) {
9666 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9667 retval |= UA_PrintContext_addString(ctx, str: "{");
9668 ctx->depth++;
9669 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9670 retval |= UA_PrintContext_addName(ctx, name: "NamespaceIndex");
9671 retval |= printUInt16(ctx, p: &p->namespaceIndex, NULL);
9672 retval |= UA_PrintContext_addString(ctx, str: ",");
9673 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9674 retval |= UA_PrintContext_addName(ctx, name: "Name");
9675 retval |= printString(ctx, p: &p->name, NULL);
9676 ctx->depth--;
9677 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9678 retval |= UA_PrintContext_addString(ctx, str: "}");
9679 return retval;
9680}
9681
9682static UA_StatusCode
9683printLocalizedText(UA_PrintContext *ctx, const UA_LocalizedText *p, const UA_DataType *_) {
9684 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9685 retval |= UA_PrintContext_addString(ctx, str: "{");
9686 ctx->depth++;
9687 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9688 retval |= UA_PrintContext_addName(ctx, name: "Locale");
9689 retval |= printString(ctx, p: &p->locale, NULL);
9690 retval |= UA_PrintContext_addString(ctx, str: ",");
9691 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9692 retval |= UA_PrintContext_addName(ctx, name: "Text");
9693 retval |= printString(ctx, p: &p->text, NULL);
9694 ctx->depth--;
9695 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9696 retval |= UA_PrintContext_addString(ctx, str: "}");
9697 return retval;
9698}
9699
9700static UA_StatusCode
9701printVariant(UA_PrintContext *ctx, const UA_Variant *p, const UA_DataType *_) {
9702 if(!p->type)
9703 return UA_PrintContext_addString(ctx, str: "NullVariant");
9704
9705 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9706 retval |= UA_PrintContext_addString(ctx, str: "{");
9707 ctx->depth++;
9708
9709 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9710 retval |= UA_PrintContext_addName(ctx, name: "DataType");
9711 retval |= UA_PrintContext_addString(ctx, str: p->type->typeName);
9712 retval |= UA_PrintContext_addString(ctx, str: ",");
9713
9714 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9715 retval |= UA_PrintContext_addName(ctx, name: "Value");
9716 if(UA_Variant_isScalar(v: p))
9717 retval |= printJumpTable[p->type->typeKind](ctx, p->data, p->type);
9718 else
9719 retval |= printArray(ctx, p: p->data, length: p->arrayLength, type: p->type);
9720
9721 if(p->arrayDimensionsSize > 0) {
9722 retval |= UA_PrintContext_addString(ctx, str: ",");
9723 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9724 retval |= UA_PrintContext_addName(ctx, name: "ArrayDimensions");
9725 retval |= printArray(ctx, p: p->arrayDimensions, length: p->arrayDimensionsSize,
9726 type: &UA_TYPES[UA_TYPES_UINT32]);
9727 }
9728
9729 ctx->depth--;
9730 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9731 retval |= UA_PrintContext_addString(ctx, str: "}");
9732 return retval;
9733}
9734
9735static UA_StatusCode
9736printExtensionObject(UA_PrintContext *ctx, const UA_ExtensionObject*p,
9737 const UA_DataType *_) {
9738 UA_StatusCode res = UA_STATUSCODE_GOOD;
9739 switch(p->encoding) {
9740 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
9741 return UA_PrintContext_addString(ctx, str: "ExtensionObject(No Body)");
9742 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
9743 res |= UA_PrintContext_addString(ctx, str: "ExtensionObject(Binary Encoded) {");
9744 ctx->depth++;
9745 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9746 res |= UA_PrintContext_addName(ctx, name: "DataType");
9747 res |= printNodeId(ctx, p: &p->content.encoded.typeId, NULL);
9748 res |= UA_PrintContext_addString(ctx, str: ",");
9749 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9750 res |= UA_PrintContext_addName(ctx, name: "Body");
9751 res |= printByteString(ctx, p: &p->content.encoded.body, NULL);
9752 ctx->depth--;
9753 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9754 res |= UA_PrintContext_addName(ctx, name: "}");
9755 break;
9756 case UA_EXTENSIONOBJECT_ENCODED_XML:
9757 res |= UA_PrintContext_addString(ctx, str: "ExtensionObject(XML Encoded) {");
9758 ctx->depth++;
9759 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9760 res |= UA_PrintContext_addName(ctx, name: "DataType");
9761 res |= printNodeId(ctx, p: &p->content.encoded.typeId, NULL);
9762 res |= UA_PrintContext_addString(ctx, str: ",");
9763 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9764 res |= UA_PrintContext_addName(ctx, name: "Body");
9765 res |= printString(ctx, p: (const UA_String*)&p->content.encoded.body, NULL);
9766 ctx->depth--;
9767 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9768 res |= UA_PrintContext_addName(ctx, name: "}");
9769 break;
9770 case UA_EXTENSIONOBJECT_DECODED:
9771 case UA_EXTENSIONOBJECT_DECODED_NODELETE:
9772 res |= UA_PrintContext_addString(ctx, str: "ExtensionObject {");
9773 ctx->depth++;
9774 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9775 res |= UA_PrintContext_addName(ctx, name: "DataType");
9776 res |= UA_PrintContext_addString(ctx, str: p->content.decoded.type->typeName);
9777 res |= UA_PrintContext_addString(ctx, str: ",");
9778 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9779 res |= UA_PrintContext_addName(ctx, name: "Body");
9780 res |= printJumpTable[p->content.decoded.type->typeKind](ctx,
9781 p->content.decoded.data,
9782 p->content.decoded.type);
9783 ctx->depth--;
9784 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9785 res |= UA_PrintContext_addName(ctx, name: "}");
9786 break;
9787 default:
9788 res = UA_STATUSCODE_BADINTERNALERROR;
9789 break;
9790 }
9791 return res;
9792}
9793
9794static UA_StatusCode
9795printDataValue(UA_PrintContext *ctx, const UA_DataValue *p, const UA_DataType *_) {
9796 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9797 retval |= UA_PrintContext_addString(ctx, str: "{");
9798 ctx->depth++;
9799 UA_Boolean comma = false;
9800
9801 if(p->hasValue) {
9802 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9803 retval |= UA_PrintContext_addName(ctx, name: "Value");
9804 retval |= printVariant(ctx, p: &p->value, NULL);
9805 comma = true;
9806 }
9807
9808 if(p->hasStatus) {
9809 if(comma)
9810 retval |= UA_PrintContext_addString(ctx, str: ",");
9811 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9812 retval |= UA_PrintContext_addName(ctx, name: "Status");
9813 retval |= printStatusCode(ctx, p: &p->status, NULL);
9814 comma = true;
9815 }
9816
9817 if(p->hasSourceTimestamp) {
9818 if(comma)
9819 retval |= UA_PrintContext_addString(ctx, str: ",");
9820 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9821 retval |= UA_PrintContext_addName(ctx, name: "SourceTimestamp");
9822 retval |= printDateTime(ctx, p: &p->sourceTimestamp, NULL);
9823 comma = true;
9824 }
9825
9826 if(p->hasSourcePicoseconds) {
9827 if(comma)
9828 retval |= UA_PrintContext_addString(ctx, str: ",");
9829 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9830 retval |= UA_PrintContext_addName(ctx, name: "SourcePicoseconds");
9831 retval |= printUInt16(ctx, p: &p->sourcePicoseconds, NULL);
9832 comma = true;
9833 }
9834
9835 if(p->hasServerTimestamp) {
9836 if(comma)
9837 retval |= UA_PrintContext_addString(ctx, str: ",");
9838 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9839 retval |= UA_PrintContext_addName(ctx, name: "ServerTimestamp");
9840 retval |= printDateTime(ctx, p: &p->serverTimestamp, NULL);
9841 comma = true;
9842 }
9843
9844 if(p->hasServerPicoseconds) {
9845 if(comma)
9846 retval |= UA_PrintContext_addString(ctx, str: ",");
9847 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9848 retval |= UA_PrintContext_addName(ctx, name: "ServerPicoseconds");
9849 retval |= printUInt16(ctx, p: &p->serverPicoseconds, NULL);
9850 comma = true;
9851 }
9852
9853 ctx->depth--;
9854 if(comma) {
9855 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9856 retval |= UA_PrintContext_addString(ctx, str: "}");
9857 } else {
9858 retval |= UA_PrintContext_addString(ctx, str: " }");
9859 }
9860 return retval;
9861}
9862
9863static UA_StatusCode
9864printDiagnosticInfo(UA_PrintContext *ctx, const UA_DiagnosticInfo *p, const UA_DataType *_) {
9865 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9866 retval |= UA_PrintContext_addString(ctx, str: "{");
9867 ctx->depth++;
9868 UA_Boolean comma = false;
9869
9870 if(p->hasSymbolicId) {
9871 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9872 retval |= UA_PrintContext_addName(ctx, name: "SymbolicId");
9873 retval |= printInt32(ctx, p: &p->symbolicId, NULL);
9874 comma = true;
9875 }
9876
9877 if(p->hasNamespaceUri) {
9878 if(comma)
9879 retval |= UA_PrintContext_addString(ctx, str: ",");
9880 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9881 retval |= UA_PrintContext_addName(ctx, name: "NamespaceUri");
9882 retval |= printInt32(ctx, p: &p->namespaceUri, NULL);
9883 comma = true;
9884 }
9885
9886 if(p->hasLocalizedText) {
9887 if(comma)
9888 retval |= UA_PrintContext_addString(ctx, str: ",");
9889 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9890 retval |= UA_PrintContext_addName(ctx, name: "LocalizedText");
9891 retval |= printInt32(ctx, p: &p->localizedText, NULL);
9892 comma = true;
9893 }
9894
9895 if(p->hasLocale) {
9896 if(comma)
9897 retval |= UA_PrintContext_addString(ctx, str: ",");
9898 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9899 retval |= UA_PrintContext_addName(ctx, name: "Locale");
9900 retval |= printInt32(ctx, p: &p->locale, NULL);
9901 comma = true;
9902 }
9903
9904 if(p->hasAdditionalInfo) {
9905 if(comma)
9906 retval |= UA_PrintContext_addString(ctx, str: ",");
9907 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9908 retval |= UA_PrintContext_addName(ctx, name: "AdditionalInfo");
9909 retval |= printString(ctx, p: &p->additionalInfo, NULL);
9910 comma = true;
9911 }
9912
9913 if(p->hasInnerStatusCode) {
9914 if(comma)
9915 retval |= UA_PrintContext_addString(ctx, str: ",");
9916 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9917 retval |= UA_PrintContext_addName(ctx, name: "InnerStatusCode");
9918 retval |= printStatusCode(ctx, p: &p->innerStatusCode, NULL);
9919 comma = true;
9920 }
9921
9922 if(p->hasInnerDiagnosticInfo) {
9923 if(comma)
9924 retval |= UA_PrintContext_addString(ctx, str: ",");
9925 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9926 retval |= UA_PrintContext_addName(ctx, name: "InnerDiagnosticInfo");
9927 retval |= printDiagnosticInfo(ctx, p: p->innerDiagnosticInfo, NULL);
9928 comma = true;
9929 }
9930
9931 ctx->depth--;
9932 if(comma) {
9933 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9934 retval |= UA_PrintContext_addString(ctx, str: "}");
9935 } else {
9936 retval |= UA_PrintContext_addString(ctx, str: " }");
9937 }
9938 return retval;
9939}
9940
9941static UA_StatusCode
9942printArray(UA_PrintContext *ctx, const void *p, const size_t length,
9943 const UA_DataType *type) {
9944 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9945 if(!p) {
9946 retval |= UA_PrintContext_addString(ctx, str: "Array(-1, ");
9947 retval |= UA_PrintContext_addString(ctx, str: type->typeName);
9948 retval |= UA_PrintContext_addString(ctx, str: ")");
9949 return retval;
9950 }
9951
9952 UA_UInt32 length32 = (UA_UInt32)length;
9953 retval |= UA_PrintContext_addString(ctx, str: "Array(");
9954 retval |= printUInt32(ctx, p: &length32, NULL);
9955 retval |= UA_PrintContext_addString(ctx, str: ", ");
9956 retval |= UA_PrintContext_addString(ctx, str: type->typeName);
9957 retval |= UA_PrintContext_addString(ctx, str: ") {");
9958 ctx->depth++;
9959 uintptr_t target = (uintptr_t)p;
9960 for(UA_UInt32 i = 0; i < length; i++) {
9961 UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9962 printUInt32(ctx, p: &i, NULL);
9963 retval |= UA_PrintContext_addString(ctx, str: ": ");
9964 printJumpTable[type->typeKind](ctx, (const void*)target, type);
9965 if(i < length - 1)
9966 retval |= UA_PrintContext_addString(ctx, str: ",");
9967 target += type->memSize;
9968 }
9969 ctx->depth--;
9970 UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9971 retval |= UA_PrintContext_addString(ctx, str: "}");
9972 return retval;
9973}
9974
9975static UA_StatusCode
9976printStructure(UA_PrintContext *ctx, const void *p, const UA_DataType *type) {
9977 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9978 uintptr_t ptrs = (uintptr_t)p;
9979 retval |= UA_PrintContext_addString(ctx, str: "{");
9980 ctx->depth++;
9981 for(size_t i = 0; i < type->membersSize; ++i) {
9982 UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9983 const UA_DataTypeMember *m = &type->members[i];
9984 const UA_DataType *mt = m->memberType;
9985 ptrs += m->padding;
9986 retval |= UA_PrintContext_addName(ctx, name: m->memberName);
9987 if(!m->isArray) {
9988 retval |= printJumpTable[mt->typeKind](ctx, (const void *)ptrs, mt);
9989 ptrs += mt->memSize;
9990 } else {
9991 const size_t size = *((const size_t*)ptrs);
9992 ptrs += sizeof(size_t);
9993 retval |= printArray(ctx, p: *(void* const*)ptrs, length: size, type: mt);
9994 ptrs += sizeof(void*);
9995 }
9996 if(i < (size_t)(type->membersSize - 1))
9997 retval |= UA_PrintContext_addString(ctx, str: ",");
9998 }
9999 ctx->depth--;
10000 UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
10001 retval |= UA_PrintContext_addString(ctx, str: "}");
10002 return retval;
10003}
10004
10005static UA_StatusCode
10006printNotImplemented(UA_PrintContext *ctx, const void *p, const UA_DataType *type) {
10007 UA_StatusCode res = UA_STATUSCODE_GOOD;
10008 res |= UA_PrintContext_addString(ctx, str: type->typeName);
10009 res |= UA_PrintContext_addString(ctx, str: " (Printing Not Implemented)");
10010 return res;
10011}
10012
10013const UA_printSignature printJumpTable[UA_DATATYPEKINDS] = {
10014 (UA_printSignature)printBoolean,
10015 (UA_printSignature)printSByte,
10016 (UA_printSignature)printByte,
10017 (UA_printSignature)printInt16,
10018 (UA_printSignature)printUInt16,
10019 (UA_printSignature)printInt32,
10020 (UA_printSignature)printUInt32,
10021 (UA_printSignature)printInt64,
10022 (UA_printSignature)printUInt64,
10023 (UA_printSignature)printFloat,
10024 (UA_printSignature)printDouble,
10025 (UA_printSignature)printString,
10026 (UA_printSignature)printDateTime,
10027 (UA_printSignature)printGuid,
10028 (UA_printSignature)printByteString,
10029 (UA_printSignature)printString, /* XmlElement */
10030 (UA_printSignature)printNodeId,
10031 (UA_printSignature)printExpandedNodeId,
10032 (UA_printSignature)printStatusCode,
10033 (UA_printSignature)printQualifiedName,
10034 (UA_printSignature)printLocalizedText,
10035 (UA_printSignature)printExtensionObject,
10036 (UA_printSignature)printDataValue,
10037 (UA_printSignature)printVariant,
10038 (UA_printSignature)printDiagnosticInfo,
10039 (UA_printSignature)printNotImplemented, /* Decimal */
10040 (UA_printSignature)printUInt32, /* Enumeration */
10041 (UA_printSignature)printStructure,
10042 (UA_printSignature)printNotImplemented, /* Structure with Optional Fields */
10043 (UA_printSignature)printNotImplemented, /* Union */
10044 (UA_printSignature)printNotImplemented /* BitfieldCluster*/
10045};
10046
10047UA_StatusCode
10048UA_print(const void *p, const UA_DataType *type, UA_String *output) {
10049 UA_PrintContext ctx;
10050 ctx.depth = 0;
10051 TAILQ_INIT(&ctx.outputs);
10052
10053 /* Encode */
10054 UA_StatusCode retval = printJumpTable[type->typeKind](&ctx, p, type);
10055
10056 /* Allocate memory for the output */
10057 if(retval == UA_STATUSCODE_GOOD) {
10058 size_t total = 0;
10059 UA_PrintOutput *out;
10060 TAILQ_FOREACH(out, &ctx.outputs, next)
10061 total += out->length;
10062 retval = UA_ByteString_allocBuffer(bs: (UA_String*)output, length: total);
10063 }
10064
10065 /* Write the output */
10066 if(retval == UA_STATUSCODE_GOOD) {
10067 size_t pos = 0;
10068 UA_PrintOutput *out;
10069 TAILQ_FOREACH(out, &ctx.outputs, next) {
10070 memcpy(dest: &output->data[pos], src: out->data, n: out->length);
10071 pos += out->length;
10072 }
10073 }
10074
10075 /* Free the context */
10076 UA_PrintOutput *o, *o2;
10077 TAILQ_FOREACH_SAFE(o, &ctx.outputs, next, o2) {
10078 TAILQ_REMOVE(&ctx.outputs, o, next);
10079 UA_free(ptr: o);
10080 }
10081 return retval;
10082}
10083
10084#endif /* UA_ENABLE_TYPEDESCRIPTION */
10085
10086/**** amalgamated original file "/build/src_generated/open62541/types_generated.c" ****/
10087
10088/**********************************
10089 * Autogenerated -- do not modify *
10090 **********************************/
10091
10092
10093/* Boolean */
10094#define Boolean_members NULL
10095
10096/* SByte */
10097#define SByte_members NULL
10098
10099/* Byte */
10100#define Byte_members NULL
10101
10102/* Int16 */
10103#define Int16_members NULL
10104
10105/* UInt16 */
10106#define UInt16_members NULL
10107
10108/* Int32 */
10109#define Int32_members NULL
10110
10111/* UInt32 */
10112#define UInt32_members NULL
10113
10114/* Int64 */
10115#define Int64_members NULL
10116
10117/* UInt64 */
10118#define UInt64_members NULL
10119
10120/* Float */
10121#define Float_members NULL
10122
10123/* Double */
10124#define Double_members NULL
10125
10126/* String */
10127#define String_members NULL
10128
10129/* DateTime */
10130#define DateTime_members NULL
10131
10132/* Guid */
10133#define Guid_members NULL
10134
10135/* ByteString */
10136#define ByteString_members NULL
10137
10138/* XmlElement */
10139#define XmlElement_members NULL
10140
10141/* NodeId */
10142#define NodeId_members NULL
10143
10144/* ExpandedNodeId */
10145#define ExpandedNodeId_members NULL
10146
10147/* StatusCode */
10148#define StatusCode_members NULL
10149
10150/* QualifiedName */
10151#define QualifiedName_members NULL
10152
10153/* LocalizedText */
10154#define LocalizedText_members NULL
10155
10156/* ExtensionObject */
10157#define ExtensionObject_members NULL
10158
10159/* DataValue */
10160#define DataValue_members NULL
10161
10162/* Variant */
10163#define Variant_members NULL
10164
10165/* DiagnosticInfo */
10166#define DiagnosticInfo_members NULL
10167
10168/* KeyValuePair */
10169static UA_DataTypeMember KeyValuePair_members[2] = {
10170{
10171 UA_TYPENAME("Key") /* .memberName */
10172 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
10173 0, /* .padding */
10174 false, /* .isArray */
10175 false /* .isOptional */
10176},
10177{
10178 UA_TYPENAME("Value") /* .memberName */
10179 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
10180 offsetof(UA_KeyValuePair, value) - offsetof(UA_KeyValuePair, key) - sizeof(UA_QualifiedName), /* .padding */
10181 false, /* .isArray */
10182 false /* .isOptional */
10183},};
10184
10185/* NodeClass */
10186#define NodeClass_members NULL
10187
10188/* StructureType */
10189#define StructureType_members NULL
10190
10191/* StructureField */
10192static UA_DataTypeMember StructureField_members[7] = {
10193{
10194 UA_TYPENAME("Name") /* .memberName */
10195 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10196 0, /* .padding */
10197 false, /* .isArray */
10198 false /* .isOptional */
10199},
10200{
10201 UA_TYPENAME("Description") /* .memberName */
10202 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10203 offsetof(UA_StructureField, description) - offsetof(UA_StructureField, name) - sizeof(UA_String), /* .padding */
10204 false, /* .isArray */
10205 false /* .isOptional */
10206},
10207{
10208 UA_TYPENAME("DataType") /* .memberName */
10209 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10210 offsetof(UA_StructureField, dataType) - offsetof(UA_StructureField, description) - sizeof(UA_LocalizedText), /* .padding */
10211 false, /* .isArray */
10212 false /* .isOptional */
10213},
10214{
10215 UA_TYPENAME("ValueRank") /* .memberName */
10216 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
10217 offsetof(UA_StructureField, valueRank) - offsetof(UA_StructureField, dataType) - sizeof(UA_NodeId), /* .padding */
10218 false, /* .isArray */
10219 false /* .isOptional */
10220},
10221{
10222 UA_TYPENAME("ArrayDimensions") /* .memberName */
10223 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10224 offsetof(UA_StructureField, arrayDimensionsSize) - offsetof(UA_StructureField, valueRank) - sizeof(UA_Int32), /* .padding */
10225 true, /* .isArray */
10226 false /* .isOptional */
10227},
10228{
10229 UA_TYPENAME("MaxStringLength") /* .memberName */
10230 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10231 offsetof(UA_StructureField, maxStringLength) - offsetof(UA_StructureField, arrayDimensions) - sizeof(void *), /* .padding */
10232 false, /* .isArray */
10233 false /* .isOptional */
10234},
10235{
10236 UA_TYPENAME("IsOptional") /* .memberName */
10237 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
10238 offsetof(UA_StructureField, isOptional) - offsetof(UA_StructureField, maxStringLength) - sizeof(UA_UInt32), /* .padding */
10239 false, /* .isArray */
10240 false /* .isOptional */
10241},};
10242
10243/* StructureDefinition */
10244static UA_DataTypeMember StructureDefinition_members[4] = {
10245{
10246 UA_TYPENAME("DefaultEncodingId") /* .memberName */
10247 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10248 0, /* .padding */
10249 false, /* .isArray */
10250 false /* .isOptional */
10251},
10252{
10253 UA_TYPENAME("BaseDataType") /* .memberName */
10254 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10255 offsetof(UA_StructureDefinition, baseDataType) - offsetof(UA_StructureDefinition, defaultEncodingId) - sizeof(UA_NodeId), /* .padding */
10256 false, /* .isArray */
10257 false /* .isOptional */
10258},
10259{
10260 UA_TYPENAME("StructureType") /* .memberName */
10261 &UA_TYPES[UA_TYPES_STRUCTURETYPE], /* .memberType */
10262 offsetof(UA_StructureDefinition, structureType) - offsetof(UA_StructureDefinition, baseDataType) - sizeof(UA_NodeId), /* .padding */
10263 false, /* .isArray */
10264 false /* .isOptional */
10265},
10266{
10267 UA_TYPENAME("Fields") /* .memberName */
10268 &UA_TYPES[UA_TYPES_STRUCTUREFIELD], /* .memberType */
10269 offsetof(UA_StructureDefinition, fieldsSize) - offsetof(UA_StructureDefinition, structureType) - sizeof(UA_StructureType), /* .padding */
10270 true, /* .isArray */
10271 false /* .isOptional */
10272},};
10273
10274/* Argument */
10275static UA_DataTypeMember Argument_members[5] = {
10276{
10277 UA_TYPENAME("Name") /* .memberName */
10278 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10279 0, /* .padding */
10280 false, /* .isArray */
10281 false /* .isOptional */
10282},
10283{
10284 UA_TYPENAME("DataType") /* .memberName */
10285 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10286 offsetof(UA_Argument, dataType) - offsetof(UA_Argument, name) - sizeof(UA_String), /* .padding */
10287 false, /* .isArray */
10288 false /* .isOptional */
10289},
10290{
10291 UA_TYPENAME("ValueRank") /* .memberName */
10292 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
10293 offsetof(UA_Argument, valueRank) - offsetof(UA_Argument, dataType) - sizeof(UA_NodeId), /* .padding */
10294 false, /* .isArray */
10295 false /* .isOptional */
10296},
10297{
10298 UA_TYPENAME("ArrayDimensions") /* .memberName */
10299 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10300 offsetof(UA_Argument, arrayDimensionsSize) - offsetof(UA_Argument, valueRank) - sizeof(UA_Int32), /* .padding */
10301 true, /* .isArray */
10302 false /* .isOptional */
10303},
10304{
10305 UA_TYPENAME("Description") /* .memberName */
10306 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10307 offsetof(UA_Argument, description) - offsetof(UA_Argument, arrayDimensions) - sizeof(void *), /* .padding */
10308 false, /* .isArray */
10309 false /* .isOptional */
10310},};
10311
10312/* EnumValueType */
10313static UA_DataTypeMember EnumValueType_members[3] = {
10314{
10315 UA_TYPENAME("Value") /* .memberName */
10316 &UA_TYPES[UA_TYPES_INT64], /* .memberType */
10317 0, /* .padding */
10318 false, /* .isArray */
10319 false /* .isOptional */
10320},
10321{
10322 UA_TYPENAME("DisplayName") /* .memberName */
10323 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10324 offsetof(UA_EnumValueType, displayName) - offsetof(UA_EnumValueType, value) - sizeof(UA_Int64), /* .padding */
10325 false, /* .isArray */
10326 false /* .isOptional */
10327},
10328{
10329 UA_TYPENAME("Description") /* .memberName */
10330 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10331 offsetof(UA_EnumValueType, description) - offsetof(UA_EnumValueType, displayName) - sizeof(UA_LocalizedText), /* .padding */
10332 false, /* .isArray */
10333 false /* .isOptional */
10334},};
10335
10336/* EnumField */
10337static UA_DataTypeMember EnumField_members[4] = {
10338{
10339 UA_TYPENAME("Value") /* .memberName */
10340 &UA_TYPES[UA_TYPES_INT64], /* .memberType */
10341 0, /* .padding */
10342 false, /* .isArray */
10343 false /* .isOptional */
10344},
10345{
10346 UA_TYPENAME("DisplayName") /* .memberName */
10347 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10348 offsetof(UA_EnumField, displayName) - offsetof(UA_EnumField, value) - sizeof(UA_Int64), /* .padding */
10349 false, /* .isArray */
10350 false /* .isOptional */
10351},
10352{
10353 UA_TYPENAME("Description") /* .memberName */
10354 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10355 offsetof(UA_EnumField, description) - offsetof(UA_EnumField, displayName) - sizeof(UA_LocalizedText), /* .padding */
10356 false, /* .isArray */
10357 false /* .isOptional */
10358},
10359{
10360 UA_TYPENAME("Name") /* .memberName */
10361 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10362 offsetof(UA_EnumField, name) - offsetof(UA_EnumField, description) - sizeof(UA_LocalizedText), /* .padding */
10363 false, /* .isArray */
10364 false /* .isOptional */
10365},};
10366
10367/* Duration */
10368#define Duration_members NULL
10369
10370/* UtcTime */
10371#define UtcTime_members NULL
10372
10373/* LocaleId */
10374#define LocaleId_members NULL
10375
10376/* TimeZoneDataType */
10377static UA_DataTypeMember TimeZoneDataType_members[2] = {
10378{
10379 UA_TYPENAME("Offset") /* .memberName */
10380 &UA_TYPES[UA_TYPES_INT16], /* .memberType */
10381 0, /* .padding */
10382 false, /* .isArray */
10383 false /* .isOptional */
10384},
10385{
10386 UA_TYPENAME("DaylightSavingInOffset") /* .memberName */
10387 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
10388 offsetof(UA_TimeZoneDataType, daylightSavingInOffset) - offsetof(UA_TimeZoneDataType, offset) - sizeof(UA_Int16), /* .padding */
10389 false, /* .isArray */
10390 false /* .isOptional */
10391},};
10392
10393/* ApplicationType */
10394#define ApplicationType_members NULL
10395
10396/* ApplicationDescription */
10397static UA_DataTypeMember ApplicationDescription_members[7] = {
10398{
10399 UA_TYPENAME("ApplicationUri") /* .memberName */
10400 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10401 0, /* .padding */
10402 false, /* .isArray */
10403 false /* .isOptional */
10404},
10405{
10406 UA_TYPENAME("ProductUri") /* .memberName */
10407 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10408 offsetof(UA_ApplicationDescription, productUri) - offsetof(UA_ApplicationDescription, applicationUri) - sizeof(UA_String), /* .padding */
10409 false, /* .isArray */
10410 false /* .isOptional */
10411},
10412{
10413 UA_TYPENAME("ApplicationName") /* .memberName */
10414 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10415 offsetof(UA_ApplicationDescription, applicationName) - offsetof(UA_ApplicationDescription, productUri) - sizeof(UA_String), /* .padding */
10416 false, /* .isArray */
10417 false /* .isOptional */
10418},
10419{
10420 UA_TYPENAME("ApplicationType") /* .memberName */
10421 &UA_TYPES[UA_TYPES_APPLICATIONTYPE], /* .memberType */
10422 offsetof(UA_ApplicationDescription, applicationType) - offsetof(UA_ApplicationDescription, applicationName) - sizeof(UA_LocalizedText), /* .padding */
10423 false, /* .isArray */
10424 false /* .isOptional */
10425},
10426{
10427 UA_TYPENAME("GatewayServerUri") /* .memberName */
10428 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10429 offsetof(UA_ApplicationDescription, gatewayServerUri) - offsetof(UA_ApplicationDescription, applicationType) - sizeof(UA_ApplicationType), /* .padding */
10430 false, /* .isArray */
10431 false /* .isOptional */
10432},
10433{
10434 UA_TYPENAME("DiscoveryProfileUri") /* .memberName */
10435 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10436 offsetof(UA_ApplicationDescription, discoveryProfileUri) - offsetof(UA_ApplicationDescription, gatewayServerUri) - sizeof(UA_String), /* .padding */
10437 false, /* .isArray */
10438 false /* .isOptional */
10439},
10440{
10441 UA_TYPENAME("DiscoveryUrls") /* .memberName */
10442 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10443 offsetof(UA_ApplicationDescription, discoveryUrlsSize) - offsetof(UA_ApplicationDescription, discoveryProfileUri) - sizeof(UA_String), /* .padding */
10444 true, /* .isArray */
10445 false /* .isOptional */
10446},};
10447
10448/* RequestHeader */
10449static UA_DataTypeMember RequestHeader_members[7] = {
10450{
10451 UA_TYPENAME("AuthenticationToken") /* .memberName */
10452 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10453 0, /* .padding */
10454 false, /* .isArray */
10455 false /* .isOptional */
10456},
10457{
10458 UA_TYPENAME("Timestamp") /* .memberName */
10459 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
10460 offsetof(UA_RequestHeader, timestamp) - offsetof(UA_RequestHeader, authenticationToken) - sizeof(UA_NodeId), /* .padding */
10461 false, /* .isArray */
10462 false /* .isOptional */
10463},
10464{
10465 UA_TYPENAME("RequestHandle") /* .memberName */
10466 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10467 offsetof(UA_RequestHeader, requestHandle) - offsetof(UA_RequestHeader, timestamp) - sizeof(UA_DateTime), /* .padding */
10468 false, /* .isArray */
10469 false /* .isOptional */
10470},
10471{
10472 UA_TYPENAME("ReturnDiagnostics") /* .memberName */
10473 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10474 offsetof(UA_RequestHeader, returnDiagnostics) - offsetof(UA_RequestHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */
10475 false, /* .isArray */
10476 false /* .isOptional */
10477},
10478{
10479 UA_TYPENAME("AuditEntryId") /* .memberName */
10480 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10481 offsetof(UA_RequestHeader, auditEntryId) - offsetof(UA_RequestHeader, returnDiagnostics) - sizeof(UA_UInt32), /* .padding */
10482 false, /* .isArray */
10483 false /* .isOptional */
10484},
10485{
10486 UA_TYPENAME("TimeoutHint") /* .memberName */
10487 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10488 offsetof(UA_RequestHeader, timeoutHint) - offsetof(UA_RequestHeader, auditEntryId) - sizeof(UA_String), /* .padding */
10489 false, /* .isArray */
10490 false /* .isOptional */
10491},
10492{
10493 UA_TYPENAME("AdditionalHeader") /* .memberName */
10494 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
10495 offsetof(UA_RequestHeader, additionalHeader) - offsetof(UA_RequestHeader, timeoutHint) - sizeof(UA_UInt32), /* .padding */
10496 false, /* .isArray */
10497 false /* .isOptional */
10498},};
10499
10500/* ResponseHeader */
10501static UA_DataTypeMember ResponseHeader_members[6] = {
10502{
10503 UA_TYPENAME("Timestamp") /* .memberName */
10504 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
10505 0, /* .padding */
10506 false, /* .isArray */
10507 false /* .isOptional */
10508},
10509{
10510 UA_TYPENAME("RequestHandle") /* .memberName */
10511 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10512 offsetof(UA_ResponseHeader, requestHandle) - offsetof(UA_ResponseHeader, timestamp) - sizeof(UA_DateTime), /* .padding */
10513 false, /* .isArray */
10514 false /* .isOptional */
10515},
10516{
10517 UA_TYPENAME("ServiceResult") /* .memberName */
10518 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
10519 offsetof(UA_ResponseHeader, serviceResult) - offsetof(UA_ResponseHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */
10520 false, /* .isArray */
10521 false /* .isOptional */
10522},
10523{
10524 UA_TYPENAME("ServiceDiagnostics") /* .memberName */
10525 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
10526 offsetof(UA_ResponseHeader, serviceDiagnostics) - offsetof(UA_ResponseHeader, serviceResult) - sizeof(UA_StatusCode), /* .padding */
10527 false, /* .isArray */
10528 false /* .isOptional */
10529},
10530{
10531 UA_TYPENAME("StringTable") /* .memberName */
10532 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10533 offsetof(UA_ResponseHeader, stringTableSize) - offsetof(UA_ResponseHeader, serviceDiagnostics) - sizeof(UA_DiagnosticInfo), /* .padding */
10534 true, /* .isArray */
10535 false /* .isOptional */
10536},
10537{
10538 UA_TYPENAME("AdditionalHeader") /* .memberName */
10539 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
10540 offsetof(UA_ResponseHeader, additionalHeader) - offsetof(UA_ResponseHeader, stringTable) - sizeof(void *), /* .padding */
10541 false, /* .isArray */
10542 false /* .isOptional */
10543},};
10544
10545/* ServiceFault */
10546static UA_DataTypeMember ServiceFault_members[1] = {
10547{
10548 UA_TYPENAME("ResponseHeader") /* .memberName */
10549 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10550 0, /* .padding */
10551 false, /* .isArray */
10552 false /* .isOptional */
10553},};
10554
10555/* FindServersRequest */
10556static UA_DataTypeMember FindServersRequest_members[4] = {
10557{
10558 UA_TYPENAME("RequestHeader") /* .memberName */
10559 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10560 0, /* .padding */
10561 false, /* .isArray */
10562 false /* .isOptional */
10563},
10564{
10565 UA_TYPENAME("EndpointUrl") /* .memberName */
10566 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10567 offsetof(UA_FindServersRequest, endpointUrl) - offsetof(UA_FindServersRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
10568 false, /* .isArray */
10569 false /* .isOptional */
10570},
10571{
10572 UA_TYPENAME("LocaleIds") /* .memberName */
10573 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10574 offsetof(UA_FindServersRequest, localeIdsSize) - offsetof(UA_FindServersRequest, endpointUrl) - sizeof(UA_String), /* .padding */
10575 true, /* .isArray */
10576 false /* .isOptional */
10577},
10578{
10579 UA_TYPENAME("ServerUris") /* .memberName */
10580 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10581 offsetof(UA_FindServersRequest, serverUrisSize) - offsetof(UA_FindServersRequest, localeIds) - sizeof(void *), /* .padding */
10582 true, /* .isArray */
10583 false /* .isOptional */
10584},};
10585
10586/* FindServersResponse */
10587static UA_DataTypeMember FindServersResponse_members[2] = {
10588{
10589 UA_TYPENAME("ResponseHeader") /* .memberName */
10590 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10591 0, /* .padding */
10592 false, /* .isArray */
10593 false /* .isOptional */
10594},
10595{
10596 UA_TYPENAME("Servers") /* .memberName */
10597 &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
10598 offsetof(UA_FindServersResponse, serversSize) - offsetof(UA_FindServersResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
10599 true, /* .isArray */
10600 false /* .isOptional */
10601},};
10602
10603/* MessageSecurityMode */
10604#define MessageSecurityMode_members NULL
10605
10606/* UserTokenType */
10607#define UserTokenType_members NULL
10608
10609/* UserTokenPolicy */
10610static UA_DataTypeMember UserTokenPolicy_members[5] = {
10611{
10612 UA_TYPENAME("PolicyId") /* .memberName */
10613 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10614 0, /* .padding */
10615 false, /* .isArray */
10616 false /* .isOptional */
10617},
10618{
10619 UA_TYPENAME("TokenType") /* .memberName */
10620 &UA_TYPES[UA_TYPES_USERTOKENTYPE], /* .memberType */
10621 offsetof(UA_UserTokenPolicy, tokenType) - offsetof(UA_UserTokenPolicy, policyId) - sizeof(UA_String), /* .padding */
10622 false, /* .isArray */
10623 false /* .isOptional */
10624},
10625{
10626 UA_TYPENAME("IssuedTokenType") /* .memberName */
10627 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10628 offsetof(UA_UserTokenPolicy, issuedTokenType) - offsetof(UA_UserTokenPolicy, tokenType) - sizeof(UA_UserTokenType), /* .padding */
10629 false, /* .isArray */
10630 false /* .isOptional */
10631},
10632{
10633 UA_TYPENAME("IssuerEndpointUrl") /* .memberName */
10634 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10635 offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - offsetof(UA_UserTokenPolicy, issuedTokenType) - sizeof(UA_String), /* .padding */
10636 false, /* .isArray */
10637 false /* .isOptional */
10638},
10639{
10640 UA_TYPENAME("SecurityPolicyUri") /* .memberName */
10641 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10642 offsetof(UA_UserTokenPolicy, securityPolicyUri) - offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - sizeof(UA_String), /* .padding */
10643 false, /* .isArray */
10644 false /* .isOptional */
10645},};
10646
10647/* EndpointDescription */
10648static UA_DataTypeMember EndpointDescription_members[8] = {
10649{
10650 UA_TYPENAME("EndpointUrl") /* .memberName */
10651 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10652 0, /* .padding */
10653 false, /* .isArray */
10654 false /* .isOptional */
10655},
10656{
10657 UA_TYPENAME("Server") /* .memberName */
10658 &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
10659 offsetof(UA_EndpointDescription, server) - offsetof(UA_EndpointDescription, endpointUrl) - sizeof(UA_String), /* .padding */
10660 false, /* .isArray */
10661 false /* .isOptional */
10662},
10663{
10664 UA_TYPENAME("ServerCertificate") /* .memberName */
10665 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10666 offsetof(UA_EndpointDescription, serverCertificate) - offsetof(UA_EndpointDescription, server) - sizeof(UA_ApplicationDescription), /* .padding */
10667 false, /* .isArray */
10668 false /* .isOptional */
10669},
10670{
10671 UA_TYPENAME("SecurityMode") /* .memberName */
10672 &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */
10673 offsetof(UA_EndpointDescription, securityMode) - offsetof(UA_EndpointDescription, serverCertificate) - sizeof(UA_ByteString), /* .padding */
10674 false, /* .isArray */
10675 false /* .isOptional */
10676},
10677{
10678 UA_TYPENAME("SecurityPolicyUri") /* .memberName */
10679 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10680 offsetof(UA_EndpointDescription, securityPolicyUri) - offsetof(UA_EndpointDescription, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
10681 false, /* .isArray */
10682 false /* .isOptional */
10683},
10684{
10685 UA_TYPENAME("UserIdentityTokens") /* .memberName */
10686 &UA_TYPES[UA_TYPES_USERTOKENPOLICY], /* .memberType */
10687 offsetof(UA_EndpointDescription, userIdentityTokensSize) - offsetof(UA_EndpointDescription, securityPolicyUri) - sizeof(UA_String), /* .padding */
10688 true, /* .isArray */
10689 false /* .isOptional */
10690},
10691{
10692 UA_TYPENAME("TransportProfileUri") /* .memberName */
10693 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10694 offsetof(UA_EndpointDescription, transportProfileUri) - offsetof(UA_EndpointDescription, userIdentityTokens) - sizeof(void *), /* .padding */
10695 false, /* .isArray */
10696 false /* .isOptional */
10697},
10698{
10699 UA_TYPENAME("SecurityLevel") /* .memberName */
10700 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
10701 offsetof(UA_EndpointDescription, securityLevel) - offsetof(UA_EndpointDescription, transportProfileUri) - sizeof(UA_String), /* .padding */
10702 false, /* .isArray */
10703 false /* .isOptional */
10704},};
10705
10706/* GetEndpointsRequest */
10707static UA_DataTypeMember GetEndpointsRequest_members[4] = {
10708{
10709 UA_TYPENAME("RequestHeader") /* .memberName */
10710 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10711 0, /* .padding */
10712 false, /* .isArray */
10713 false /* .isOptional */
10714},
10715{
10716 UA_TYPENAME("EndpointUrl") /* .memberName */
10717 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10718 offsetof(UA_GetEndpointsRequest, endpointUrl) - offsetof(UA_GetEndpointsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
10719 false, /* .isArray */
10720 false /* .isOptional */
10721},
10722{
10723 UA_TYPENAME("LocaleIds") /* .memberName */
10724 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10725 offsetof(UA_GetEndpointsRequest, localeIdsSize) - offsetof(UA_GetEndpointsRequest, endpointUrl) - sizeof(UA_String), /* .padding */
10726 true, /* .isArray */
10727 false /* .isOptional */
10728},
10729{
10730 UA_TYPENAME("ProfileUris") /* .memberName */
10731 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10732 offsetof(UA_GetEndpointsRequest, profileUrisSize) - offsetof(UA_GetEndpointsRequest, localeIds) - sizeof(void *), /* .padding */
10733 true, /* .isArray */
10734 false /* .isOptional */
10735},};
10736
10737/* GetEndpointsResponse */
10738static UA_DataTypeMember GetEndpointsResponse_members[2] = {
10739{
10740 UA_TYPENAME("ResponseHeader") /* .memberName */
10741 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10742 0, /* .padding */
10743 false, /* .isArray */
10744 false /* .isOptional */
10745},
10746{
10747 UA_TYPENAME("Endpoints") /* .memberName */
10748 &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */
10749 offsetof(UA_GetEndpointsResponse, endpointsSize) - offsetof(UA_GetEndpointsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
10750 true, /* .isArray */
10751 false /* .isOptional */
10752},};
10753
10754/* SecurityTokenRequestType */
10755#define SecurityTokenRequestType_members NULL
10756
10757/* ChannelSecurityToken */
10758static UA_DataTypeMember ChannelSecurityToken_members[4] = {
10759{
10760 UA_TYPENAME("ChannelId") /* .memberName */
10761 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10762 0, /* .padding */
10763 false, /* .isArray */
10764 false /* .isOptional */
10765},
10766{
10767 UA_TYPENAME("TokenId") /* .memberName */
10768 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10769 offsetof(UA_ChannelSecurityToken, tokenId) - offsetof(UA_ChannelSecurityToken, channelId) - sizeof(UA_UInt32), /* .padding */
10770 false, /* .isArray */
10771 false /* .isOptional */
10772},
10773{
10774 UA_TYPENAME("CreatedAt") /* .memberName */
10775 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
10776 offsetof(UA_ChannelSecurityToken, createdAt) - offsetof(UA_ChannelSecurityToken, tokenId) - sizeof(UA_UInt32), /* .padding */
10777 false, /* .isArray */
10778 false /* .isOptional */
10779},
10780{
10781 UA_TYPENAME("RevisedLifetime") /* .memberName */
10782 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10783 offsetof(UA_ChannelSecurityToken, revisedLifetime) - offsetof(UA_ChannelSecurityToken, createdAt) - sizeof(UA_DateTime), /* .padding */
10784 false, /* .isArray */
10785 false /* .isOptional */
10786},};
10787
10788/* OpenSecureChannelRequest */
10789static UA_DataTypeMember OpenSecureChannelRequest_members[6] = {
10790{
10791 UA_TYPENAME("RequestHeader") /* .memberName */
10792 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10793 0, /* .padding */
10794 false, /* .isArray */
10795 false /* .isOptional */
10796},
10797{
10798 UA_TYPENAME("ClientProtocolVersion") /* .memberName */
10799 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10800 offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - offsetof(UA_OpenSecureChannelRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
10801 false, /* .isArray */
10802 false /* .isOptional */
10803},
10804{
10805 UA_TYPENAME("RequestType") /* .memberName */
10806 &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE], /* .memberType */
10807 offsetof(UA_OpenSecureChannelRequest, requestType) - offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - sizeof(UA_UInt32), /* .padding */
10808 false, /* .isArray */
10809 false /* .isOptional */
10810},
10811{
10812 UA_TYPENAME("SecurityMode") /* .memberName */
10813 &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */
10814 offsetof(UA_OpenSecureChannelRequest, securityMode) - offsetof(UA_OpenSecureChannelRequest, requestType) - sizeof(UA_SecurityTokenRequestType), /* .padding */
10815 false, /* .isArray */
10816 false /* .isOptional */
10817},
10818{
10819 UA_TYPENAME("ClientNonce") /* .memberName */
10820 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10821 offsetof(UA_OpenSecureChannelRequest, clientNonce) - offsetof(UA_OpenSecureChannelRequest, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
10822 false, /* .isArray */
10823 false /* .isOptional */
10824},
10825{
10826 UA_TYPENAME("RequestedLifetime") /* .memberName */
10827 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10828 offsetof(UA_OpenSecureChannelRequest, requestedLifetime) - offsetof(UA_OpenSecureChannelRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */
10829 false, /* .isArray */
10830 false /* .isOptional */
10831},};
10832
10833/* OpenSecureChannelResponse */
10834static UA_DataTypeMember OpenSecureChannelResponse_members[4] = {
10835{
10836 UA_TYPENAME("ResponseHeader") /* .memberName */
10837 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10838 0, /* .padding */
10839 false, /* .isArray */
10840 false /* .isOptional */
10841},
10842{
10843 UA_TYPENAME("ServerProtocolVersion") /* .memberName */
10844 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10845 offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - offsetof(UA_OpenSecureChannelResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
10846 false, /* .isArray */
10847 false /* .isOptional */
10848},
10849{
10850 UA_TYPENAME("SecurityToken") /* .memberName */
10851 &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN], /* .memberType */
10852 offsetof(UA_OpenSecureChannelResponse, securityToken) - offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - sizeof(UA_UInt32), /* .padding */
10853 false, /* .isArray */
10854 false /* .isOptional */
10855},
10856{
10857 UA_TYPENAME("ServerNonce") /* .memberName */
10858 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10859 offsetof(UA_OpenSecureChannelResponse, serverNonce) - offsetof(UA_OpenSecureChannelResponse, securityToken) - sizeof(UA_ChannelSecurityToken), /* .padding */
10860 false, /* .isArray */
10861 false /* .isOptional */
10862},};
10863
10864/* CloseSecureChannelRequest */
10865static UA_DataTypeMember CloseSecureChannelRequest_members[1] = {
10866{
10867 UA_TYPENAME("RequestHeader") /* .memberName */
10868 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10869 0, /* .padding */
10870 false, /* .isArray */
10871 false /* .isOptional */
10872},};
10873
10874/* CloseSecureChannelResponse */
10875static UA_DataTypeMember CloseSecureChannelResponse_members[1] = {
10876{
10877 UA_TYPENAME("ResponseHeader") /* .memberName */
10878 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10879 0, /* .padding */
10880 false, /* .isArray */
10881 false /* .isOptional */
10882},};
10883
10884/* SignedSoftwareCertificate */
10885static UA_DataTypeMember SignedSoftwareCertificate_members[2] = {
10886{
10887 UA_TYPENAME("CertificateData") /* .memberName */
10888 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10889 0, /* .padding */
10890 false, /* .isArray */
10891 false /* .isOptional */
10892},
10893{
10894 UA_TYPENAME("Signature") /* .memberName */
10895 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10896 offsetof(UA_SignedSoftwareCertificate, signature) - offsetof(UA_SignedSoftwareCertificate, certificateData) - sizeof(UA_ByteString), /* .padding */
10897 false, /* .isArray */
10898 false /* .isOptional */
10899},};
10900
10901/* SignatureData */
10902static UA_DataTypeMember SignatureData_members[2] = {
10903{
10904 UA_TYPENAME("Algorithm") /* .memberName */
10905 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10906 0, /* .padding */
10907 false, /* .isArray */
10908 false /* .isOptional */
10909},
10910{
10911 UA_TYPENAME("Signature") /* .memberName */
10912 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10913 offsetof(UA_SignatureData, signature) - offsetof(UA_SignatureData, algorithm) - sizeof(UA_String), /* .padding */
10914 false, /* .isArray */
10915 false /* .isOptional */
10916},};
10917
10918/* CreateSessionRequest */
10919static UA_DataTypeMember CreateSessionRequest_members[9] = {
10920{
10921 UA_TYPENAME("RequestHeader") /* .memberName */
10922 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10923 0, /* .padding */
10924 false, /* .isArray */
10925 false /* .isOptional */
10926},
10927{
10928 UA_TYPENAME("ClientDescription") /* .memberName */
10929 &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
10930 offsetof(UA_CreateSessionRequest, clientDescription) - offsetof(UA_CreateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
10931 false, /* .isArray */
10932 false /* .isOptional */
10933},
10934{
10935 UA_TYPENAME("ServerUri") /* .memberName */
10936 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10937 offsetof(UA_CreateSessionRequest, serverUri) - offsetof(UA_CreateSessionRequest, clientDescription) - sizeof(UA_ApplicationDescription), /* .padding */
10938 false, /* .isArray */
10939 false /* .isOptional */
10940},
10941{
10942 UA_TYPENAME("EndpointUrl") /* .memberName */
10943 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10944 offsetof(UA_CreateSessionRequest, endpointUrl) - offsetof(UA_CreateSessionRequest, serverUri) - sizeof(UA_String), /* .padding */
10945 false, /* .isArray */
10946 false /* .isOptional */
10947},
10948{
10949 UA_TYPENAME("SessionName") /* .memberName */
10950 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10951 offsetof(UA_CreateSessionRequest, sessionName) - offsetof(UA_CreateSessionRequest, endpointUrl) - sizeof(UA_String), /* .padding */
10952 false, /* .isArray */
10953 false /* .isOptional */
10954},
10955{
10956 UA_TYPENAME("ClientNonce") /* .memberName */
10957 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10958 offsetof(UA_CreateSessionRequest, clientNonce) - offsetof(UA_CreateSessionRequest, sessionName) - sizeof(UA_String), /* .padding */
10959 false, /* .isArray */
10960 false /* .isOptional */
10961},
10962{
10963 UA_TYPENAME("ClientCertificate") /* .memberName */
10964 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10965 offsetof(UA_CreateSessionRequest, clientCertificate) - offsetof(UA_CreateSessionRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */
10966 false, /* .isArray */
10967 false /* .isOptional */
10968},
10969{
10970 UA_TYPENAME("RequestedSessionTimeout") /* .memberName */
10971 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
10972 offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - offsetof(UA_CreateSessionRequest, clientCertificate) - sizeof(UA_ByteString), /* .padding */
10973 false, /* .isArray */
10974 false /* .isOptional */
10975},
10976{
10977 UA_TYPENAME("MaxResponseMessageSize") /* .memberName */
10978 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10979 offsetof(UA_CreateSessionRequest, maxResponseMessageSize) - offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - sizeof(UA_Double), /* .padding */
10980 false, /* .isArray */
10981 false /* .isOptional */
10982},};
10983
10984/* CreateSessionResponse */
10985static UA_DataTypeMember CreateSessionResponse_members[10] = {
10986{
10987 UA_TYPENAME("ResponseHeader") /* .memberName */
10988 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10989 0, /* .padding */
10990 false, /* .isArray */
10991 false /* .isOptional */
10992},
10993{
10994 UA_TYPENAME("SessionId") /* .memberName */
10995 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10996 offsetof(UA_CreateSessionResponse, sessionId) - offsetof(UA_CreateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
10997 false, /* .isArray */
10998 false /* .isOptional */
10999},
11000{
11001 UA_TYPENAME("AuthenticationToken") /* .memberName */
11002 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11003 offsetof(UA_CreateSessionResponse, authenticationToken) - offsetof(UA_CreateSessionResponse, sessionId) - sizeof(UA_NodeId), /* .padding */
11004 false, /* .isArray */
11005 false /* .isOptional */
11006},
11007{
11008 UA_TYPENAME("RevisedSessionTimeout") /* .memberName */
11009 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
11010 offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - offsetof(UA_CreateSessionResponse, authenticationToken) - sizeof(UA_NodeId), /* .padding */
11011 false, /* .isArray */
11012 false /* .isOptional */
11013},
11014{
11015 UA_TYPENAME("ServerNonce") /* .memberName */
11016 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11017 offsetof(UA_CreateSessionResponse, serverNonce) - offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - sizeof(UA_Double), /* .padding */
11018 false, /* .isArray */
11019 false /* .isOptional */
11020},
11021{
11022 UA_TYPENAME("ServerCertificate") /* .memberName */
11023 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11024 offsetof(UA_CreateSessionResponse, serverCertificate) - offsetof(UA_CreateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */
11025 false, /* .isArray */
11026 false /* .isOptional */
11027},
11028{
11029 UA_TYPENAME("ServerEndpoints") /* .memberName */
11030 &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */
11031 offsetof(UA_CreateSessionResponse, serverEndpointsSize) - offsetof(UA_CreateSessionResponse, serverCertificate) - sizeof(UA_ByteString), /* .padding */
11032 true, /* .isArray */
11033 false /* .isOptional */
11034},
11035{
11036 UA_TYPENAME("ServerSoftwareCertificates") /* .memberName */
11037 &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], /* .memberType */
11038 offsetof(UA_CreateSessionResponse, serverSoftwareCertificatesSize) - offsetof(UA_CreateSessionResponse, serverEndpoints) - sizeof(void *), /* .padding */
11039 true, /* .isArray */
11040 false /* .isOptional */
11041},
11042{
11043 UA_TYPENAME("ServerSignature") /* .memberName */
11044 &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
11045 offsetof(UA_CreateSessionResponse, serverSignature) - offsetof(UA_CreateSessionResponse, serverSoftwareCertificates) - sizeof(void *), /* .padding */
11046 false, /* .isArray */
11047 false /* .isOptional */
11048},
11049{
11050 UA_TYPENAME("MaxRequestMessageSize") /* .memberName */
11051 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11052 offsetof(UA_CreateSessionResponse, maxRequestMessageSize) - offsetof(UA_CreateSessionResponse, serverSignature) - sizeof(UA_SignatureData), /* .padding */
11053 false, /* .isArray */
11054 false /* .isOptional */
11055},};
11056
11057/* UserIdentityToken */
11058static UA_DataTypeMember UserIdentityToken_members[1] = {
11059{
11060 UA_TYPENAME("PolicyId") /* .memberName */
11061 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11062 0, /* .padding */
11063 false, /* .isArray */
11064 false /* .isOptional */
11065},};
11066
11067/* AnonymousIdentityToken */
11068static UA_DataTypeMember AnonymousIdentityToken_members[1] = {
11069{
11070 UA_TYPENAME("PolicyId") /* .memberName */
11071 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11072 0, /* .padding */
11073 false, /* .isArray */
11074 false /* .isOptional */
11075},};
11076
11077/* UserNameIdentityToken */
11078static UA_DataTypeMember UserNameIdentityToken_members[4] = {
11079{
11080 UA_TYPENAME("PolicyId") /* .memberName */
11081 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11082 0, /* .padding */
11083 false, /* .isArray */
11084 false /* .isOptional */
11085},
11086{
11087 UA_TYPENAME("UserName") /* .memberName */
11088 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11089 offsetof(UA_UserNameIdentityToken, userName) - offsetof(UA_UserNameIdentityToken, policyId) - sizeof(UA_String), /* .padding */
11090 false, /* .isArray */
11091 false /* .isOptional */
11092},
11093{
11094 UA_TYPENAME("Password") /* .memberName */
11095 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11096 offsetof(UA_UserNameIdentityToken, password) - offsetof(UA_UserNameIdentityToken, userName) - sizeof(UA_String), /* .padding */
11097 false, /* .isArray */
11098 false /* .isOptional */
11099},
11100{
11101 UA_TYPENAME("EncryptionAlgorithm") /* .memberName */
11102 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11103 offsetof(UA_UserNameIdentityToken, encryptionAlgorithm) - offsetof(UA_UserNameIdentityToken, password) - sizeof(UA_ByteString), /* .padding */
11104 false, /* .isArray */
11105 false /* .isOptional */
11106},};
11107
11108/* X509IdentityToken */
11109static UA_DataTypeMember X509IdentityToken_members[2] = {
11110{
11111 UA_TYPENAME("PolicyId") /* .memberName */
11112 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11113 0, /* .padding */
11114 false, /* .isArray */
11115 false /* .isOptional */
11116},
11117{
11118 UA_TYPENAME("CertificateData") /* .memberName */
11119 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11120 offsetof(UA_X509IdentityToken, certificateData) - offsetof(UA_X509IdentityToken, policyId) - sizeof(UA_String), /* .padding */
11121 false, /* .isArray */
11122 false /* .isOptional */
11123},};
11124
11125/* IssuedIdentityToken */
11126static UA_DataTypeMember IssuedIdentityToken_members[3] = {
11127{
11128 UA_TYPENAME("PolicyId") /* .memberName */
11129 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11130 0, /* .padding */
11131 false, /* .isArray */
11132 false /* .isOptional */
11133},
11134{
11135 UA_TYPENAME("TokenData") /* .memberName */
11136 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11137 offsetof(UA_IssuedIdentityToken, tokenData) - offsetof(UA_IssuedIdentityToken, policyId) - sizeof(UA_String), /* .padding */
11138 false, /* .isArray */
11139 false /* .isOptional */
11140},
11141{
11142 UA_TYPENAME("EncryptionAlgorithm") /* .memberName */
11143 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11144 offsetof(UA_IssuedIdentityToken, encryptionAlgorithm) - offsetof(UA_IssuedIdentityToken, tokenData) - sizeof(UA_ByteString), /* .padding */
11145 false, /* .isArray */
11146 false /* .isOptional */
11147},};
11148
11149/* ActivateSessionRequest */
11150static UA_DataTypeMember ActivateSessionRequest_members[6] = {
11151{
11152 UA_TYPENAME("RequestHeader") /* .memberName */
11153 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11154 0, /* .padding */
11155 false, /* .isArray */
11156 false /* .isOptional */
11157},
11158{
11159 UA_TYPENAME("ClientSignature") /* .memberName */
11160 &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
11161 offsetof(UA_ActivateSessionRequest, clientSignature) - offsetof(UA_ActivateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11162 false, /* .isArray */
11163 false /* .isOptional */
11164},
11165{
11166 UA_TYPENAME("ClientSoftwareCertificates") /* .memberName */
11167 &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], /* .memberType */
11168 offsetof(UA_ActivateSessionRequest, clientSoftwareCertificatesSize) - offsetof(UA_ActivateSessionRequest, clientSignature) - sizeof(UA_SignatureData), /* .padding */
11169 true, /* .isArray */
11170 false /* .isOptional */
11171},
11172{
11173 UA_TYPENAME("LocaleIds") /* .memberName */
11174 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11175 offsetof(UA_ActivateSessionRequest, localeIdsSize) - offsetof(UA_ActivateSessionRequest, clientSoftwareCertificates) - sizeof(void *), /* .padding */
11176 true, /* .isArray */
11177 false /* .isOptional */
11178},
11179{
11180 UA_TYPENAME("UserIdentityToken") /* .memberName */
11181 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
11182 offsetof(UA_ActivateSessionRequest, userIdentityToken) - offsetof(UA_ActivateSessionRequest, localeIds) - sizeof(void *), /* .padding */
11183 false, /* .isArray */
11184 false /* .isOptional */
11185},
11186{
11187 UA_TYPENAME("UserTokenSignature") /* .memberName */
11188 &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
11189 offsetof(UA_ActivateSessionRequest, userTokenSignature) - offsetof(UA_ActivateSessionRequest, userIdentityToken) - sizeof(UA_ExtensionObject), /* .padding */
11190 false, /* .isArray */
11191 false /* .isOptional */
11192},};
11193
11194/* ActivateSessionResponse */
11195static UA_DataTypeMember ActivateSessionResponse_members[4] = {
11196{
11197 UA_TYPENAME("ResponseHeader") /* .memberName */
11198 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11199 0, /* .padding */
11200 false, /* .isArray */
11201 false /* .isOptional */
11202},
11203{
11204 UA_TYPENAME("ServerNonce") /* .memberName */
11205 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11206 offsetof(UA_ActivateSessionResponse, serverNonce) - offsetof(UA_ActivateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
11207 false, /* .isArray */
11208 false /* .isOptional */
11209},
11210{
11211 UA_TYPENAME("Results") /* .memberName */
11212 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
11213 offsetof(UA_ActivateSessionResponse, resultsSize) - offsetof(UA_ActivateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */
11214 true, /* .isArray */
11215 false /* .isOptional */
11216},
11217{
11218 UA_TYPENAME("DiagnosticInfos") /* .memberName */
11219 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
11220 offsetof(UA_ActivateSessionResponse, diagnosticInfosSize) - offsetof(UA_ActivateSessionResponse, results) - sizeof(void *), /* .padding */
11221 true, /* .isArray */
11222 false /* .isOptional */
11223},};
11224
11225/* CloseSessionRequest */
11226static UA_DataTypeMember CloseSessionRequest_members[2] = {
11227{
11228 UA_TYPENAME("RequestHeader") /* .memberName */
11229 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11230 0, /* .padding */
11231 false, /* .isArray */
11232 false /* .isOptional */
11233},
11234{
11235 UA_TYPENAME("DeleteSubscriptions") /* .memberName */
11236 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11237 offsetof(UA_CloseSessionRequest, deleteSubscriptions) - offsetof(UA_CloseSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11238 false, /* .isArray */
11239 false /* .isOptional */
11240},};
11241
11242/* CloseSessionResponse */
11243static UA_DataTypeMember CloseSessionResponse_members[1] = {
11244{
11245 UA_TYPENAME("ResponseHeader") /* .memberName */
11246 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11247 0, /* .padding */
11248 false, /* .isArray */
11249 false /* .isOptional */
11250},};
11251
11252/* NodeAttributesMask */
11253#define NodeAttributesMask_members NULL
11254
11255/* NodeAttributes */
11256static UA_DataTypeMember NodeAttributes_members[5] = {
11257{
11258 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11259 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11260 0, /* .padding */
11261 false, /* .isArray */
11262 false /* .isOptional */
11263},
11264{
11265 UA_TYPENAME("DisplayName") /* .memberName */
11266 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11267 offsetof(UA_NodeAttributes, displayName) - offsetof(UA_NodeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11268 false, /* .isArray */
11269 false /* .isOptional */
11270},
11271{
11272 UA_TYPENAME("Description") /* .memberName */
11273 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11274 offsetof(UA_NodeAttributes, description) - offsetof(UA_NodeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11275 false, /* .isArray */
11276 false /* .isOptional */
11277},
11278{
11279 UA_TYPENAME("WriteMask") /* .memberName */
11280 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11281 offsetof(UA_NodeAttributes, writeMask) - offsetof(UA_NodeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11282 false, /* .isArray */
11283 false /* .isOptional */
11284},
11285{
11286 UA_TYPENAME("UserWriteMask") /* .memberName */
11287 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11288 offsetof(UA_NodeAttributes, userWriteMask) - offsetof(UA_NodeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11289 false, /* .isArray */
11290 false /* .isOptional */
11291},};
11292
11293/* ObjectAttributes */
11294static UA_DataTypeMember ObjectAttributes_members[6] = {
11295{
11296 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11297 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11298 0, /* .padding */
11299 false, /* .isArray */
11300 false /* .isOptional */
11301},
11302{
11303 UA_TYPENAME("DisplayName") /* .memberName */
11304 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11305 offsetof(UA_ObjectAttributes, displayName) - offsetof(UA_ObjectAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11306 false, /* .isArray */
11307 false /* .isOptional */
11308},
11309{
11310 UA_TYPENAME("Description") /* .memberName */
11311 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11312 offsetof(UA_ObjectAttributes, description) - offsetof(UA_ObjectAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11313 false, /* .isArray */
11314 false /* .isOptional */
11315},
11316{
11317 UA_TYPENAME("WriteMask") /* .memberName */
11318 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11319 offsetof(UA_ObjectAttributes, writeMask) - offsetof(UA_ObjectAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11320 false, /* .isArray */
11321 false /* .isOptional */
11322},
11323{
11324 UA_TYPENAME("UserWriteMask") /* .memberName */
11325 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11326 offsetof(UA_ObjectAttributes, userWriteMask) - offsetof(UA_ObjectAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11327 false, /* .isArray */
11328 false /* .isOptional */
11329},
11330{
11331 UA_TYPENAME("EventNotifier") /* .memberName */
11332 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
11333 offsetof(UA_ObjectAttributes, eventNotifier) - offsetof(UA_ObjectAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11334 false, /* .isArray */
11335 false /* .isOptional */
11336},};
11337
11338/* VariableAttributes */
11339static UA_DataTypeMember VariableAttributes_members[13] = {
11340{
11341 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11342 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11343 0, /* .padding */
11344 false, /* .isArray */
11345 false /* .isOptional */
11346},
11347{
11348 UA_TYPENAME("DisplayName") /* .memberName */
11349 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11350 offsetof(UA_VariableAttributes, displayName) - offsetof(UA_VariableAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11351 false, /* .isArray */
11352 false /* .isOptional */
11353},
11354{
11355 UA_TYPENAME("Description") /* .memberName */
11356 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11357 offsetof(UA_VariableAttributes, description) - offsetof(UA_VariableAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11358 false, /* .isArray */
11359 false /* .isOptional */
11360},
11361{
11362 UA_TYPENAME("WriteMask") /* .memberName */
11363 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11364 offsetof(UA_VariableAttributes, writeMask) - offsetof(UA_VariableAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11365 false, /* .isArray */
11366 false /* .isOptional */
11367},
11368{
11369 UA_TYPENAME("UserWriteMask") /* .memberName */
11370 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11371 offsetof(UA_VariableAttributes, userWriteMask) - offsetof(UA_VariableAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11372 false, /* .isArray */
11373 false /* .isOptional */
11374},
11375{
11376 UA_TYPENAME("Value") /* .memberName */
11377 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
11378 offsetof(UA_VariableAttributes, value) - offsetof(UA_VariableAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11379 false, /* .isArray */
11380 false /* .isOptional */
11381},
11382{
11383 UA_TYPENAME("DataType") /* .memberName */
11384 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11385 offsetof(UA_VariableAttributes, dataType) - offsetof(UA_VariableAttributes, value) - sizeof(UA_Variant), /* .padding */
11386 false, /* .isArray */
11387 false /* .isOptional */
11388},
11389{
11390 UA_TYPENAME("ValueRank") /* .memberName */
11391 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
11392 offsetof(UA_VariableAttributes, valueRank) - offsetof(UA_VariableAttributes, dataType) - sizeof(UA_NodeId), /* .padding */
11393 false, /* .isArray */
11394 false /* .isOptional */
11395},
11396{
11397 UA_TYPENAME("ArrayDimensions") /* .memberName */
11398 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11399 offsetof(UA_VariableAttributes, arrayDimensionsSize) - offsetof(UA_VariableAttributes, valueRank) - sizeof(UA_Int32), /* .padding */
11400 true, /* .isArray */
11401 false /* .isOptional */
11402},
11403{
11404 UA_TYPENAME("AccessLevel") /* .memberName */
11405 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
11406 offsetof(UA_VariableAttributes, accessLevel) - offsetof(UA_VariableAttributes, arrayDimensions) - sizeof(void *), /* .padding */
11407 false, /* .isArray */
11408 false /* .isOptional */
11409},
11410{
11411 UA_TYPENAME("UserAccessLevel") /* .memberName */
11412 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
11413 offsetof(UA_VariableAttributes, userAccessLevel) - offsetof(UA_VariableAttributes, accessLevel) - sizeof(UA_Byte), /* .padding */
11414 false, /* .isArray */
11415 false /* .isOptional */
11416},
11417{
11418 UA_TYPENAME("MinimumSamplingInterval") /* .memberName */
11419 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
11420 offsetof(UA_VariableAttributes, minimumSamplingInterval) - offsetof(UA_VariableAttributes, userAccessLevel) - sizeof(UA_Byte), /* .padding */
11421 false, /* .isArray */
11422 false /* .isOptional */
11423},
11424{
11425 UA_TYPENAME("Historizing") /* .memberName */
11426 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11427 offsetof(UA_VariableAttributes, historizing) - offsetof(UA_VariableAttributes, minimumSamplingInterval) - sizeof(UA_Double), /* .padding */
11428 false, /* .isArray */
11429 false /* .isOptional */
11430},};
11431
11432/* MethodAttributes */
11433static UA_DataTypeMember MethodAttributes_members[7] = {
11434{
11435 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11436 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11437 0, /* .padding */
11438 false, /* .isArray */
11439 false /* .isOptional */
11440},
11441{
11442 UA_TYPENAME("DisplayName") /* .memberName */
11443 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11444 offsetof(UA_MethodAttributes, displayName) - offsetof(UA_MethodAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11445 false, /* .isArray */
11446 false /* .isOptional */
11447},
11448{
11449 UA_TYPENAME("Description") /* .memberName */
11450 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11451 offsetof(UA_MethodAttributes, description) - offsetof(UA_MethodAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11452 false, /* .isArray */
11453 false /* .isOptional */
11454},
11455{
11456 UA_TYPENAME("WriteMask") /* .memberName */
11457 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11458 offsetof(UA_MethodAttributes, writeMask) - offsetof(UA_MethodAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11459 false, /* .isArray */
11460 false /* .isOptional */
11461},
11462{
11463 UA_TYPENAME("UserWriteMask") /* .memberName */
11464 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11465 offsetof(UA_MethodAttributes, userWriteMask) - offsetof(UA_MethodAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11466 false, /* .isArray */
11467 false /* .isOptional */
11468},
11469{
11470 UA_TYPENAME("Executable") /* .memberName */
11471 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11472 offsetof(UA_MethodAttributes, executable) - offsetof(UA_MethodAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11473 false, /* .isArray */
11474 false /* .isOptional */
11475},
11476{
11477 UA_TYPENAME("UserExecutable") /* .memberName */
11478 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11479 offsetof(UA_MethodAttributes, userExecutable) - offsetof(UA_MethodAttributes, executable) - sizeof(UA_Boolean), /* .padding */
11480 false, /* .isArray */
11481 false /* .isOptional */
11482},};
11483
11484/* ObjectTypeAttributes */
11485static UA_DataTypeMember ObjectTypeAttributes_members[6] = {
11486{
11487 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11488 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11489 0, /* .padding */
11490 false, /* .isArray */
11491 false /* .isOptional */
11492},
11493{
11494 UA_TYPENAME("DisplayName") /* .memberName */
11495 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11496 offsetof(UA_ObjectTypeAttributes, displayName) - offsetof(UA_ObjectTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11497 false, /* .isArray */
11498 false /* .isOptional */
11499},
11500{
11501 UA_TYPENAME("Description") /* .memberName */
11502 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11503 offsetof(UA_ObjectTypeAttributes, description) - offsetof(UA_ObjectTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11504 false, /* .isArray */
11505 false /* .isOptional */
11506},
11507{
11508 UA_TYPENAME("WriteMask") /* .memberName */
11509 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11510 offsetof(UA_ObjectTypeAttributes, writeMask) - offsetof(UA_ObjectTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11511 false, /* .isArray */
11512 false /* .isOptional */
11513},
11514{
11515 UA_TYPENAME("UserWriteMask") /* .memberName */
11516 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11517 offsetof(UA_ObjectTypeAttributes, userWriteMask) - offsetof(UA_ObjectTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11518 false, /* .isArray */
11519 false /* .isOptional */
11520},
11521{
11522 UA_TYPENAME("IsAbstract") /* .memberName */
11523 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11524 offsetof(UA_ObjectTypeAttributes, isAbstract) - offsetof(UA_ObjectTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11525 false, /* .isArray */
11526 false /* .isOptional */
11527},};
11528
11529/* VariableTypeAttributes */
11530static UA_DataTypeMember VariableTypeAttributes_members[10] = {
11531{
11532 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11533 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11534 0, /* .padding */
11535 false, /* .isArray */
11536 false /* .isOptional */
11537},
11538{
11539 UA_TYPENAME("DisplayName") /* .memberName */
11540 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11541 offsetof(UA_VariableTypeAttributes, displayName) - offsetof(UA_VariableTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11542 false, /* .isArray */
11543 false /* .isOptional */
11544},
11545{
11546 UA_TYPENAME("Description") /* .memberName */
11547 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11548 offsetof(UA_VariableTypeAttributes, description) - offsetof(UA_VariableTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11549 false, /* .isArray */
11550 false /* .isOptional */
11551},
11552{
11553 UA_TYPENAME("WriteMask") /* .memberName */
11554 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11555 offsetof(UA_VariableTypeAttributes, writeMask) - offsetof(UA_VariableTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11556 false, /* .isArray */
11557 false /* .isOptional */
11558},
11559{
11560 UA_TYPENAME("UserWriteMask") /* .memberName */
11561 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11562 offsetof(UA_VariableTypeAttributes, userWriteMask) - offsetof(UA_VariableTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11563 false, /* .isArray */
11564 false /* .isOptional */
11565},
11566{
11567 UA_TYPENAME("Value") /* .memberName */
11568 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
11569 offsetof(UA_VariableTypeAttributes, value) - offsetof(UA_VariableTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11570 false, /* .isArray */
11571 false /* .isOptional */
11572},
11573{
11574 UA_TYPENAME("DataType") /* .memberName */
11575 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11576 offsetof(UA_VariableTypeAttributes, dataType) - offsetof(UA_VariableTypeAttributes, value) - sizeof(UA_Variant), /* .padding */
11577 false, /* .isArray */
11578 false /* .isOptional */
11579},
11580{
11581 UA_TYPENAME("ValueRank") /* .memberName */
11582 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
11583 offsetof(UA_VariableTypeAttributes, valueRank) - offsetof(UA_VariableTypeAttributes, dataType) - sizeof(UA_NodeId), /* .padding */
11584 false, /* .isArray */
11585 false /* .isOptional */
11586},
11587{
11588 UA_TYPENAME("ArrayDimensions") /* .memberName */
11589 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11590 offsetof(UA_VariableTypeAttributes, arrayDimensionsSize) - offsetof(UA_VariableTypeAttributes, valueRank) - sizeof(UA_Int32), /* .padding */
11591 true, /* .isArray */
11592 false /* .isOptional */
11593},
11594{
11595 UA_TYPENAME("IsAbstract") /* .memberName */
11596 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11597 offsetof(UA_VariableTypeAttributes, isAbstract) - offsetof(UA_VariableTypeAttributes, arrayDimensions) - sizeof(void *), /* .padding */
11598 false, /* .isArray */
11599 false /* .isOptional */
11600},};
11601
11602/* ReferenceTypeAttributes */
11603static UA_DataTypeMember ReferenceTypeAttributes_members[8] = {
11604{
11605 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11606 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11607 0, /* .padding */
11608 false, /* .isArray */
11609 false /* .isOptional */
11610},
11611{
11612 UA_TYPENAME("DisplayName") /* .memberName */
11613 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11614 offsetof(UA_ReferenceTypeAttributes, displayName) - offsetof(UA_ReferenceTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11615 false, /* .isArray */
11616 false /* .isOptional */
11617},
11618{
11619 UA_TYPENAME("Description") /* .memberName */
11620 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11621 offsetof(UA_ReferenceTypeAttributes, description) - offsetof(UA_ReferenceTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11622 false, /* .isArray */
11623 false /* .isOptional */
11624},
11625{
11626 UA_TYPENAME("WriteMask") /* .memberName */
11627 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11628 offsetof(UA_ReferenceTypeAttributes, writeMask) - offsetof(UA_ReferenceTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11629 false, /* .isArray */
11630 false /* .isOptional */
11631},
11632{
11633 UA_TYPENAME("UserWriteMask") /* .memberName */
11634 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11635 offsetof(UA_ReferenceTypeAttributes, userWriteMask) - offsetof(UA_ReferenceTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11636 false, /* .isArray */
11637 false /* .isOptional */
11638},
11639{
11640 UA_TYPENAME("IsAbstract") /* .memberName */
11641 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11642 offsetof(UA_ReferenceTypeAttributes, isAbstract) - offsetof(UA_ReferenceTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11643 false, /* .isArray */
11644 false /* .isOptional */
11645},
11646{
11647 UA_TYPENAME("Symmetric") /* .memberName */
11648 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11649 offsetof(UA_ReferenceTypeAttributes, symmetric) - offsetof(UA_ReferenceTypeAttributes, isAbstract) - sizeof(UA_Boolean), /* .padding */
11650 false, /* .isArray */
11651 false /* .isOptional */
11652},
11653{
11654 UA_TYPENAME("InverseName") /* .memberName */
11655 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11656 offsetof(UA_ReferenceTypeAttributes, inverseName) - offsetof(UA_ReferenceTypeAttributes, symmetric) - sizeof(UA_Boolean), /* .padding */
11657 false, /* .isArray */
11658 false /* .isOptional */
11659},};
11660
11661/* DataTypeAttributes */
11662static UA_DataTypeMember DataTypeAttributes_members[6] = {
11663{
11664 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11665 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11666 0, /* .padding */
11667 false, /* .isArray */
11668 false /* .isOptional */
11669},
11670{
11671 UA_TYPENAME("DisplayName") /* .memberName */
11672 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11673 offsetof(UA_DataTypeAttributes, displayName) - offsetof(UA_DataTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11674 false, /* .isArray */
11675 false /* .isOptional */
11676},
11677{
11678 UA_TYPENAME("Description") /* .memberName */
11679 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11680 offsetof(UA_DataTypeAttributes, description) - offsetof(UA_DataTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11681 false, /* .isArray */
11682 false /* .isOptional */
11683},
11684{
11685 UA_TYPENAME("WriteMask") /* .memberName */
11686 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11687 offsetof(UA_DataTypeAttributes, writeMask) - offsetof(UA_DataTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11688 false, /* .isArray */
11689 false /* .isOptional */
11690},
11691{
11692 UA_TYPENAME("UserWriteMask") /* .memberName */
11693 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11694 offsetof(UA_DataTypeAttributes, userWriteMask) - offsetof(UA_DataTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11695 false, /* .isArray */
11696 false /* .isOptional */
11697},
11698{
11699 UA_TYPENAME("IsAbstract") /* .memberName */
11700 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11701 offsetof(UA_DataTypeAttributes, isAbstract) - offsetof(UA_DataTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11702 false, /* .isArray */
11703 false /* .isOptional */
11704},};
11705
11706/* ViewAttributes */
11707static UA_DataTypeMember ViewAttributes_members[7] = {
11708{
11709 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11710 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11711 0, /* .padding */
11712 false, /* .isArray */
11713 false /* .isOptional */
11714},
11715{
11716 UA_TYPENAME("DisplayName") /* .memberName */
11717 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11718 offsetof(UA_ViewAttributes, displayName) - offsetof(UA_ViewAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11719 false, /* .isArray */
11720 false /* .isOptional */
11721},
11722{
11723 UA_TYPENAME("Description") /* .memberName */
11724 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11725 offsetof(UA_ViewAttributes, description) - offsetof(UA_ViewAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11726 false, /* .isArray */
11727 false /* .isOptional */
11728},
11729{
11730 UA_TYPENAME("WriteMask") /* .memberName */
11731 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11732 offsetof(UA_ViewAttributes, writeMask) - offsetof(UA_ViewAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11733 false, /* .isArray */
11734 false /* .isOptional */
11735},
11736{
11737 UA_TYPENAME("UserWriteMask") /* .memberName */
11738 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11739 offsetof(UA_ViewAttributes, userWriteMask) - offsetof(UA_ViewAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11740 false, /* .isArray */
11741 false /* .isOptional */
11742},
11743{
11744 UA_TYPENAME("ContainsNoLoops") /* .memberName */
11745 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11746 offsetof(UA_ViewAttributes, containsNoLoops) - offsetof(UA_ViewAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11747 false, /* .isArray */
11748 false /* .isOptional */
11749},
11750{
11751 UA_TYPENAME("EventNotifier") /* .memberName */
11752 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
11753 offsetof(UA_ViewAttributes, eventNotifier) - offsetof(UA_ViewAttributes, containsNoLoops) - sizeof(UA_Boolean), /* .padding */
11754 false, /* .isArray */
11755 false /* .isOptional */
11756},};
11757
11758/* AddNodesItem */
11759static UA_DataTypeMember AddNodesItem_members[7] = {
11760{
11761 UA_TYPENAME("ParentNodeId") /* .memberName */
11762 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
11763 0, /* .padding */
11764 false, /* .isArray */
11765 false /* .isOptional */
11766},
11767{
11768 UA_TYPENAME("ReferenceTypeId") /* .memberName */
11769 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11770 offsetof(UA_AddNodesItem, referenceTypeId) - offsetof(UA_AddNodesItem, parentNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
11771 false, /* .isArray */
11772 false /* .isOptional */
11773},
11774{
11775 UA_TYPENAME("RequestedNewNodeId") /* .memberName */
11776 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
11777 offsetof(UA_AddNodesItem, requestedNewNodeId) - offsetof(UA_AddNodesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
11778 false, /* .isArray */
11779 false /* .isOptional */
11780},
11781{
11782 UA_TYPENAME("BrowseName") /* .memberName */
11783 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
11784 offsetof(UA_AddNodesItem, browseName) - offsetof(UA_AddNodesItem, requestedNewNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
11785 false, /* .isArray */
11786 false /* .isOptional */
11787},
11788{
11789 UA_TYPENAME("NodeClass") /* .memberName */
11790 &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
11791 offsetof(UA_AddNodesItem, nodeClass) - offsetof(UA_AddNodesItem, browseName) - sizeof(UA_QualifiedName), /* .padding */
11792 false, /* .isArray */
11793 false /* .isOptional */
11794},
11795{
11796 UA_TYPENAME("NodeAttributes") /* .memberName */
11797 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
11798 offsetof(UA_AddNodesItem, nodeAttributes) - offsetof(UA_AddNodesItem, nodeClass) - sizeof(UA_NodeClass), /* .padding */
11799 false, /* .isArray */
11800 false /* .isOptional */
11801},
11802{
11803 UA_TYPENAME("TypeDefinition") /* .memberName */
11804 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
11805 offsetof(UA_AddNodesItem, typeDefinition) - offsetof(UA_AddNodesItem, nodeAttributes) - sizeof(UA_ExtensionObject), /* .padding */
11806 false, /* .isArray */
11807 false /* .isOptional */
11808},};
11809
11810/* AddNodesResult */
11811static UA_DataTypeMember AddNodesResult_members[2] = {
11812{
11813 UA_TYPENAME("StatusCode") /* .memberName */
11814 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
11815 0, /* .padding */
11816 false, /* .isArray */
11817 false /* .isOptional */
11818},
11819{
11820 UA_TYPENAME("AddedNodeId") /* .memberName */
11821 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11822 offsetof(UA_AddNodesResult, addedNodeId) - offsetof(UA_AddNodesResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
11823 false, /* .isArray */
11824 false /* .isOptional */
11825},};
11826
11827/* AddNodesRequest */
11828static UA_DataTypeMember AddNodesRequest_members[2] = {
11829{
11830 UA_TYPENAME("RequestHeader") /* .memberName */
11831 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11832 0, /* .padding */
11833 false, /* .isArray */
11834 false /* .isOptional */
11835},
11836{
11837 UA_TYPENAME("NodesToAdd") /* .memberName */
11838 &UA_TYPES[UA_TYPES_ADDNODESITEM], /* .memberType */
11839 offsetof(UA_AddNodesRequest, nodesToAddSize) - offsetof(UA_AddNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11840 true, /* .isArray */
11841 false /* .isOptional */
11842},};
11843
11844/* AddNodesResponse */
11845static UA_DataTypeMember AddNodesResponse_members[3] = {
11846{
11847 UA_TYPENAME("ResponseHeader") /* .memberName */
11848 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11849 0, /* .padding */
11850 false, /* .isArray */
11851 false /* .isOptional */
11852},
11853{
11854 UA_TYPENAME("Results") /* .memberName */
11855 &UA_TYPES[UA_TYPES_ADDNODESRESULT], /* .memberType */
11856 offsetof(UA_AddNodesResponse, resultsSize) - offsetof(UA_AddNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
11857 true, /* .isArray */
11858 false /* .isOptional */
11859},
11860{
11861 UA_TYPENAME("DiagnosticInfos") /* .memberName */
11862 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
11863 offsetof(UA_AddNodesResponse, diagnosticInfosSize) - offsetof(UA_AddNodesResponse, results) - sizeof(void *), /* .padding */
11864 true, /* .isArray */
11865 false /* .isOptional */
11866},};
11867
11868/* AddReferencesItem */
11869static UA_DataTypeMember AddReferencesItem_members[6] = {
11870{
11871 UA_TYPENAME("SourceNodeId") /* .memberName */
11872 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11873 0, /* .padding */
11874 false, /* .isArray */
11875 false /* .isOptional */
11876},
11877{
11878 UA_TYPENAME("ReferenceTypeId") /* .memberName */
11879 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11880 offsetof(UA_AddReferencesItem, referenceTypeId) - offsetof(UA_AddReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */
11881 false, /* .isArray */
11882 false /* .isOptional */
11883},
11884{
11885 UA_TYPENAME("IsForward") /* .memberName */
11886 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11887 offsetof(UA_AddReferencesItem, isForward) - offsetof(UA_AddReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
11888 false, /* .isArray */
11889 false /* .isOptional */
11890},
11891{
11892 UA_TYPENAME("TargetServerUri") /* .memberName */
11893 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11894 offsetof(UA_AddReferencesItem, targetServerUri) - offsetof(UA_AddReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */
11895 false, /* .isArray */
11896 false /* .isOptional */
11897},
11898{
11899 UA_TYPENAME("TargetNodeId") /* .memberName */
11900 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
11901 offsetof(UA_AddReferencesItem, targetNodeId) - offsetof(UA_AddReferencesItem, targetServerUri) - sizeof(UA_String), /* .padding */
11902 false, /* .isArray */
11903 false /* .isOptional */
11904},
11905{
11906 UA_TYPENAME("TargetNodeClass") /* .memberName */
11907 &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
11908 offsetof(UA_AddReferencesItem, targetNodeClass) - offsetof(UA_AddReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
11909 false, /* .isArray */
11910 false /* .isOptional */
11911},};
11912
11913/* AddReferencesRequest */
11914static UA_DataTypeMember AddReferencesRequest_members[2] = {
11915{
11916 UA_TYPENAME("RequestHeader") /* .memberName */
11917 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11918 0, /* .padding */
11919 false, /* .isArray */
11920 false /* .isOptional */
11921},
11922{
11923 UA_TYPENAME("ReferencesToAdd") /* .memberName */
11924 &UA_TYPES[UA_TYPES_ADDREFERENCESITEM], /* .memberType */
11925 offsetof(UA_AddReferencesRequest, referencesToAddSize) - offsetof(UA_AddReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11926 true, /* .isArray */
11927 false /* .isOptional */
11928},};
11929
11930/* AddReferencesResponse */
11931static UA_DataTypeMember AddReferencesResponse_members[3] = {
11932{
11933 UA_TYPENAME("ResponseHeader") /* .memberName */
11934 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11935 0, /* .padding */
11936 false, /* .isArray */
11937 false /* .isOptional */
11938},
11939{
11940 UA_TYPENAME("Results") /* .memberName */
11941 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
11942 offsetof(UA_AddReferencesResponse, resultsSize) - offsetof(UA_AddReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
11943 true, /* .isArray */
11944 false /* .isOptional */
11945},
11946{
11947 UA_TYPENAME("DiagnosticInfos") /* .memberName */
11948 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
11949 offsetof(UA_AddReferencesResponse, diagnosticInfosSize) - offsetof(UA_AddReferencesResponse, results) - sizeof(void *), /* .padding */
11950 true, /* .isArray */
11951 false /* .isOptional */
11952},};
11953
11954/* DeleteNodesItem */
11955static UA_DataTypeMember DeleteNodesItem_members[2] = {
11956{
11957 UA_TYPENAME("NodeId") /* .memberName */
11958 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11959 0, /* .padding */
11960 false, /* .isArray */
11961 false /* .isOptional */
11962},
11963{
11964 UA_TYPENAME("DeleteTargetReferences") /* .memberName */
11965 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11966 offsetof(UA_DeleteNodesItem, deleteTargetReferences) - offsetof(UA_DeleteNodesItem, nodeId) - sizeof(UA_NodeId), /* .padding */
11967 false, /* .isArray */
11968 false /* .isOptional */
11969},};
11970
11971/* DeleteNodesRequest */
11972static UA_DataTypeMember DeleteNodesRequest_members[2] = {
11973{
11974 UA_TYPENAME("RequestHeader") /* .memberName */
11975 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11976 0, /* .padding */
11977 false, /* .isArray */
11978 false /* .isOptional */
11979},
11980{
11981 UA_TYPENAME("NodesToDelete") /* .memberName */
11982 &UA_TYPES[UA_TYPES_DELETENODESITEM], /* .memberType */
11983 offsetof(UA_DeleteNodesRequest, nodesToDeleteSize) - offsetof(UA_DeleteNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11984 true, /* .isArray */
11985 false /* .isOptional */
11986},};
11987
11988/* DeleteNodesResponse */
11989static UA_DataTypeMember DeleteNodesResponse_members[3] = {
11990{
11991 UA_TYPENAME("ResponseHeader") /* .memberName */
11992 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11993 0, /* .padding */
11994 false, /* .isArray */
11995 false /* .isOptional */
11996},
11997{
11998 UA_TYPENAME("Results") /* .memberName */
11999 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12000 offsetof(UA_DeleteNodesResponse, resultsSize) - offsetof(UA_DeleteNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12001 true, /* .isArray */
12002 false /* .isOptional */
12003},
12004{
12005 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12006 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12007 offsetof(UA_DeleteNodesResponse, diagnosticInfosSize) - offsetof(UA_DeleteNodesResponse, results) - sizeof(void *), /* .padding */
12008 true, /* .isArray */
12009 false /* .isOptional */
12010},};
12011
12012/* DeleteReferencesItem */
12013static UA_DataTypeMember DeleteReferencesItem_members[5] = {
12014{
12015 UA_TYPENAME("SourceNodeId") /* .memberName */
12016 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12017 0, /* .padding */
12018 false, /* .isArray */
12019 false /* .isOptional */
12020},
12021{
12022 UA_TYPENAME("ReferenceTypeId") /* .memberName */
12023 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12024 offsetof(UA_DeleteReferencesItem, referenceTypeId) - offsetof(UA_DeleteReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */
12025 false, /* .isArray */
12026 false /* .isOptional */
12027},
12028{
12029 UA_TYPENAME("IsForward") /* .memberName */
12030 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12031 offsetof(UA_DeleteReferencesItem, isForward) - offsetof(UA_DeleteReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
12032 false, /* .isArray */
12033 false /* .isOptional */
12034},
12035{
12036 UA_TYPENAME("TargetNodeId") /* .memberName */
12037 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
12038 offsetof(UA_DeleteReferencesItem, targetNodeId) - offsetof(UA_DeleteReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */
12039 false, /* .isArray */
12040 false /* .isOptional */
12041},
12042{
12043 UA_TYPENAME("DeleteBidirectional") /* .memberName */
12044 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12045 offsetof(UA_DeleteReferencesItem, deleteBidirectional) - offsetof(UA_DeleteReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
12046 false, /* .isArray */
12047 false /* .isOptional */
12048},};
12049
12050/* DeleteReferencesRequest */
12051static UA_DataTypeMember DeleteReferencesRequest_members[2] = {
12052{
12053 UA_TYPENAME("RequestHeader") /* .memberName */
12054 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12055 0, /* .padding */
12056 false, /* .isArray */
12057 false /* .isOptional */
12058},
12059{
12060 UA_TYPENAME("ReferencesToDelete") /* .memberName */
12061 &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM], /* .memberType */
12062 offsetof(UA_DeleteReferencesRequest, referencesToDeleteSize) - offsetof(UA_DeleteReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12063 true, /* .isArray */
12064 false /* .isOptional */
12065},};
12066
12067/* DeleteReferencesResponse */
12068static UA_DataTypeMember DeleteReferencesResponse_members[3] = {
12069{
12070 UA_TYPENAME("ResponseHeader") /* .memberName */
12071 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12072 0, /* .padding */
12073 false, /* .isArray */
12074 false /* .isOptional */
12075},
12076{
12077 UA_TYPENAME("Results") /* .memberName */
12078 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12079 offsetof(UA_DeleteReferencesResponse, resultsSize) - offsetof(UA_DeleteReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12080 true, /* .isArray */
12081 false /* .isOptional */
12082},
12083{
12084 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12085 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12086 offsetof(UA_DeleteReferencesResponse, diagnosticInfosSize) - offsetof(UA_DeleteReferencesResponse, results) - sizeof(void *), /* .padding */
12087 true, /* .isArray */
12088 false /* .isOptional */
12089},};
12090
12091/* BrowseDirection */
12092#define BrowseDirection_members NULL
12093
12094/* ViewDescription */
12095static UA_DataTypeMember ViewDescription_members[3] = {
12096{
12097 UA_TYPENAME("ViewId") /* .memberName */
12098 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12099 0, /* .padding */
12100 false, /* .isArray */
12101 false /* .isOptional */
12102},
12103{
12104 UA_TYPENAME("Timestamp") /* .memberName */
12105 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
12106 offsetof(UA_ViewDescription, timestamp) - offsetof(UA_ViewDescription, viewId) - sizeof(UA_NodeId), /* .padding */
12107 false, /* .isArray */
12108 false /* .isOptional */
12109},
12110{
12111 UA_TYPENAME("ViewVersion") /* .memberName */
12112 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12113 offsetof(UA_ViewDescription, viewVersion) - offsetof(UA_ViewDescription, timestamp) - sizeof(UA_DateTime), /* .padding */
12114 false, /* .isArray */
12115 false /* .isOptional */
12116},};
12117
12118/* BrowseDescription */
12119static UA_DataTypeMember BrowseDescription_members[6] = {
12120{
12121 UA_TYPENAME("NodeId") /* .memberName */
12122 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12123 0, /* .padding */
12124 false, /* .isArray */
12125 false /* .isOptional */
12126},
12127{
12128 UA_TYPENAME("BrowseDirection") /* .memberName */
12129 &UA_TYPES[UA_TYPES_BROWSEDIRECTION], /* .memberType */
12130 offsetof(UA_BrowseDescription, browseDirection) - offsetof(UA_BrowseDescription, nodeId) - sizeof(UA_NodeId), /* .padding */
12131 false, /* .isArray */
12132 false /* .isOptional */
12133},
12134{
12135 UA_TYPENAME("ReferenceTypeId") /* .memberName */
12136 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12137 offsetof(UA_BrowseDescription, referenceTypeId) - offsetof(UA_BrowseDescription, browseDirection) - sizeof(UA_BrowseDirection), /* .padding */
12138 false, /* .isArray */
12139 false /* .isOptional */
12140},
12141{
12142 UA_TYPENAME("IncludeSubtypes") /* .memberName */
12143 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12144 offsetof(UA_BrowseDescription, includeSubtypes) - offsetof(UA_BrowseDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
12145 false, /* .isArray */
12146 false /* .isOptional */
12147},
12148{
12149 UA_TYPENAME("NodeClassMask") /* .memberName */
12150 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12151 offsetof(UA_BrowseDescription, nodeClassMask) - offsetof(UA_BrowseDescription, includeSubtypes) - sizeof(UA_Boolean), /* .padding */
12152 false, /* .isArray */
12153 false /* .isOptional */
12154},
12155{
12156 UA_TYPENAME("ResultMask") /* .memberName */
12157 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12158 offsetof(UA_BrowseDescription, resultMask) - offsetof(UA_BrowseDescription, nodeClassMask) - sizeof(UA_UInt32), /* .padding */
12159 false, /* .isArray */
12160 false /* .isOptional */
12161},};
12162
12163/* BrowseResultMask */
12164#define BrowseResultMask_members NULL
12165
12166/* ReferenceDescription */
12167static UA_DataTypeMember ReferenceDescription_members[7] = {
12168{
12169 UA_TYPENAME("ReferenceTypeId") /* .memberName */
12170 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12171 0, /* .padding */
12172 false, /* .isArray */
12173 false /* .isOptional */
12174},
12175{
12176 UA_TYPENAME("IsForward") /* .memberName */
12177 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12178 offsetof(UA_ReferenceDescription, isForward) - offsetof(UA_ReferenceDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
12179 false, /* .isArray */
12180 false /* .isOptional */
12181},
12182{
12183 UA_TYPENAME("NodeId") /* .memberName */
12184 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
12185 offsetof(UA_ReferenceDescription, nodeId) - offsetof(UA_ReferenceDescription, isForward) - sizeof(UA_Boolean), /* .padding */
12186 false, /* .isArray */
12187 false /* .isOptional */
12188},
12189{
12190 UA_TYPENAME("BrowseName") /* .memberName */
12191 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12192 offsetof(UA_ReferenceDescription, browseName) - offsetof(UA_ReferenceDescription, nodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
12193 false, /* .isArray */
12194 false /* .isOptional */
12195},
12196{
12197 UA_TYPENAME("DisplayName") /* .memberName */
12198 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
12199 offsetof(UA_ReferenceDescription, displayName) - offsetof(UA_ReferenceDescription, browseName) - sizeof(UA_QualifiedName), /* .padding */
12200 false, /* .isArray */
12201 false /* .isOptional */
12202},
12203{
12204 UA_TYPENAME("NodeClass") /* .memberName */
12205 &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
12206 offsetof(UA_ReferenceDescription, nodeClass) - offsetof(UA_ReferenceDescription, displayName) - sizeof(UA_LocalizedText), /* .padding */
12207 false, /* .isArray */
12208 false /* .isOptional */
12209},
12210{
12211 UA_TYPENAME("TypeDefinition") /* .memberName */
12212 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
12213 offsetof(UA_ReferenceDescription, typeDefinition) - offsetof(UA_ReferenceDescription, nodeClass) - sizeof(UA_NodeClass), /* .padding */
12214 false, /* .isArray */
12215 false /* .isOptional */
12216},};
12217
12218/* BrowseResult */
12219static UA_DataTypeMember BrowseResult_members[3] = {
12220{
12221 UA_TYPENAME("StatusCode") /* .memberName */
12222 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12223 0, /* .padding */
12224 false, /* .isArray */
12225 false /* .isOptional */
12226},
12227{
12228 UA_TYPENAME("ContinuationPoint") /* .memberName */
12229 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
12230 offsetof(UA_BrowseResult, continuationPoint) - offsetof(UA_BrowseResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
12231 false, /* .isArray */
12232 false /* .isOptional */
12233},
12234{
12235 UA_TYPENAME("References") /* .memberName */
12236 &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], /* .memberType */
12237 offsetof(UA_BrowseResult, referencesSize) - offsetof(UA_BrowseResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */
12238 true, /* .isArray */
12239 false /* .isOptional */
12240},};
12241
12242/* BrowseRequest */
12243static UA_DataTypeMember BrowseRequest_members[4] = {
12244{
12245 UA_TYPENAME("RequestHeader") /* .memberName */
12246 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12247 0, /* .padding */
12248 false, /* .isArray */
12249 false /* .isOptional */
12250},
12251{
12252 UA_TYPENAME("View") /* .memberName */
12253 &UA_TYPES[UA_TYPES_VIEWDESCRIPTION], /* .memberType */
12254 offsetof(UA_BrowseRequest, view) - offsetof(UA_BrowseRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12255 false, /* .isArray */
12256 false /* .isOptional */
12257},
12258{
12259 UA_TYPENAME("RequestedMaxReferencesPerNode") /* .memberName */
12260 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12261 offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - offsetof(UA_BrowseRequest, view) - sizeof(UA_ViewDescription), /* .padding */
12262 false, /* .isArray */
12263 false /* .isOptional */
12264},
12265{
12266 UA_TYPENAME("NodesToBrowse") /* .memberName */
12267 &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION], /* .memberType */
12268 offsetof(UA_BrowseRequest, nodesToBrowseSize) - offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - sizeof(UA_UInt32), /* .padding */
12269 true, /* .isArray */
12270 false /* .isOptional */
12271},};
12272
12273/* BrowseResponse */
12274static UA_DataTypeMember BrowseResponse_members[3] = {
12275{
12276 UA_TYPENAME("ResponseHeader") /* .memberName */
12277 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12278 0, /* .padding */
12279 false, /* .isArray */
12280 false /* .isOptional */
12281},
12282{
12283 UA_TYPENAME("Results") /* .memberName */
12284 &UA_TYPES[UA_TYPES_BROWSERESULT], /* .memberType */
12285 offsetof(UA_BrowseResponse, resultsSize) - offsetof(UA_BrowseResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12286 true, /* .isArray */
12287 false /* .isOptional */
12288},
12289{
12290 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12291 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12292 offsetof(UA_BrowseResponse, diagnosticInfosSize) - offsetof(UA_BrowseResponse, results) - sizeof(void *), /* .padding */
12293 true, /* .isArray */
12294 false /* .isOptional */
12295},};
12296
12297/* BrowseNextRequest */
12298static UA_DataTypeMember BrowseNextRequest_members[3] = {
12299{
12300 UA_TYPENAME("RequestHeader") /* .memberName */
12301 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12302 0, /* .padding */
12303 false, /* .isArray */
12304 false /* .isOptional */
12305},
12306{
12307 UA_TYPENAME("ReleaseContinuationPoints") /* .memberName */
12308 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12309 offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - offsetof(UA_BrowseNextRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12310 false, /* .isArray */
12311 false /* .isOptional */
12312},
12313{
12314 UA_TYPENAME("ContinuationPoints") /* .memberName */
12315 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
12316 offsetof(UA_BrowseNextRequest, continuationPointsSize) - offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */
12317 true, /* .isArray */
12318 false /* .isOptional */
12319},};
12320
12321/* BrowseNextResponse */
12322static UA_DataTypeMember BrowseNextResponse_members[3] = {
12323{
12324 UA_TYPENAME("ResponseHeader") /* .memberName */
12325 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12326 0, /* .padding */
12327 false, /* .isArray */
12328 false /* .isOptional */
12329},
12330{
12331 UA_TYPENAME("Results") /* .memberName */
12332 &UA_TYPES[UA_TYPES_BROWSERESULT], /* .memberType */
12333 offsetof(UA_BrowseNextResponse, resultsSize) - offsetof(UA_BrowseNextResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12334 true, /* .isArray */
12335 false /* .isOptional */
12336},
12337{
12338 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12339 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12340 offsetof(UA_BrowseNextResponse, diagnosticInfosSize) - offsetof(UA_BrowseNextResponse, results) - sizeof(void *), /* .padding */
12341 true, /* .isArray */
12342 false /* .isOptional */
12343},};
12344
12345/* RelativePathElement */
12346static UA_DataTypeMember RelativePathElement_members[4] = {
12347{
12348 UA_TYPENAME("ReferenceTypeId") /* .memberName */
12349 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12350 0, /* .padding */
12351 false, /* .isArray */
12352 false /* .isOptional */
12353},
12354{
12355 UA_TYPENAME("IsInverse") /* .memberName */
12356 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12357 offsetof(UA_RelativePathElement, isInverse) - offsetof(UA_RelativePathElement, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
12358 false, /* .isArray */
12359 false /* .isOptional */
12360},
12361{
12362 UA_TYPENAME("IncludeSubtypes") /* .memberName */
12363 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12364 offsetof(UA_RelativePathElement, includeSubtypes) - offsetof(UA_RelativePathElement, isInverse) - sizeof(UA_Boolean), /* .padding */
12365 false, /* .isArray */
12366 false /* .isOptional */
12367},
12368{
12369 UA_TYPENAME("TargetName") /* .memberName */
12370 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12371 offsetof(UA_RelativePathElement, targetName) - offsetof(UA_RelativePathElement, includeSubtypes) - sizeof(UA_Boolean), /* .padding */
12372 false, /* .isArray */
12373 false /* .isOptional */
12374},};
12375
12376/* RelativePath */
12377static UA_DataTypeMember RelativePath_members[1] = {
12378{
12379 UA_TYPENAME("Elements") /* .memberName */
12380 &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT], /* .memberType */
12381 0, /* .padding */
12382 true, /* .isArray */
12383 false /* .isOptional */
12384},};
12385
12386/* BrowsePath */
12387static UA_DataTypeMember BrowsePath_members[2] = {
12388{
12389 UA_TYPENAME("StartingNode") /* .memberName */
12390 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12391 0, /* .padding */
12392 false, /* .isArray */
12393 false /* .isOptional */
12394},
12395{
12396 UA_TYPENAME("RelativePath") /* .memberName */
12397 &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */
12398 offsetof(UA_BrowsePath, relativePath) - offsetof(UA_BrowsePath, startingNode) - sizeof(UA_NodeId), /* .padding */
12399 false, /* .isArray */
12400 false /* .isOptional */
12401},};
12402
12403/* BrowsePathTarget */
12404static UA_DataTypeMember BrowsePathTarget_members[2] = {
12405{
12406 UA_TYPENAME("TargetId") /* .memberName */
12407 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
12408 0, /* .padding */
12409 false, /* .isArray */
12410 false /* .isOptional */
12411},
12412{
12413 UA_TYPENAME("RemainingPathIndex") /* .memberName */
12414 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12415 offsetof(UA_BrowsePathTarget, remainingPathIndex) - offsetof(UA_BrowsePathTarget, targetId) - sizeof(UA_ExpandedNodeId), /* .padding */
12416 false, /* .isArray */
12417 false /* .isOptional */
12418},};
12419
12420/* BrowsePathResult */
12421static UA_DataTypeMember BrowsePathResult_members[2] = {
12422{
12423 UA_TYPENAME("StatusCode") /* .memberName */
12424 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12425 0, /* .padding */
12426 false, /* .isArray */
12427 false /* .isOptional */
12428},
12429{
12430 UA_TYPENAME("Targets") /* .memberName */
12431 &UA_TYPES[UA_TYPES_BROWSEPATHTARGET], /* .memberType */
12432 offsetof(UA_BrowsePathResult, targetsSize) - offsetof(UA_BrowsePathResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
12433 true, /* .isArray */
12434 false /* .isOptional */
12435},};
12436
12437/* TranslateBrowsePathsToNodeIdsRequest */
12438static UA_DataTypeMember TranslateBrowsePathsToNodeIdsRequest_members[2] = {
12439{
12440 UA_TYPENAME("RequestHeader") /* .memberName */
12441 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12442 0, /* .padding */
12443 false, /* .isArray */
12444 false /* .isOptional */
12445},
12446{
12447 UA_TYPENAME("BrowsePaths") /* .memberName */
12448 &UA_TYPES[UA_TYPES_BROWSEPATH], /* .memberType */
12449 offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, browsePathsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12450 true, /* .isArray */
12451 false /* .isOptional */
12452},};
12453
12454/* TranslateBrowsePathsToNodeIdsResponse */
12455static UA_DataTypeMember TranslateBrowsePathsToNodeIdsResponse_members[3] = {
12456{
12457 UA_TYPENAME("ResponseHeader") /* .memberName */
12458 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12459 0, /* .padding */
12460 false, /* .isArray */
12461 false /* .isOptional */
12462},
12463{
12464 UA_TYPENAME("Results") /* .memberName */
12465 &UA_TYPES[UA_TYPES_BROWSEPATHRESULT], /* .memberType */
12466 offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, resultsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12467 true, /* .isArray */
12468 false /* .isOptional */
12469},
12470{
12471 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12472 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12473 offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, diagnosticInfosSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, results) - sizeof(void *), /* .padding */
12474 true, /* .isArray */
12475 false /* .isOptional */
12476},};
12477
12478/* RegisterNodesRequest */
12479static UA_DataTypeMember RegisterNodesRequest_members[2] = {
12480{
12481 UA_TYPENAME("RequestHeader") /* .memberName */
12482 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12483 0, /* .padding */
12484 false, /* .isArray */
12485 false /* .isOptional */
12486},
12487{
12488 UA_TYPENAME("NodesToRegister") /* .memberName */
12489 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12490 offsetof(UA_RegisterNodesRequest, nodesToRegisterSize) - offsetof(UA_RegisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12491 true, /* .isArray */
12492 false /* .isOptional */
12493},};
12494
12495/* RegisterNodesResponse */
12496static UA_DataTypeMember RegisterNodesResponse_members[2] = {
12497{
12498 UA_TYPENAME("ResponseHeader") /* .memberName */
12499 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12500 0, /* .padding */
12501 false, /* .isArray */
12502 false /* .isOptional */
12503},
12504{
12505 UA_TYPENAME("RegisteredNodeIds") /* .memberName */
12506 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12507 offsetof(UA_RegisterNodesResponse, registeredNodeIdsSize) - offsetof(UA_RegisterNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12508 true, /* .isArray */
12509 false /* .isOptional */
12510},};
12511
12512/* UnregisterNodesRequest */
12513static UA_DataTypeMember UnregisterNodesRequest_members[2] = {
12514{
12515 UA_TYPENAME("RequestHeader") /* .memberName */
12516 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12517 0, /* .padding */
12518 false, /* .isArray */
12519 false /* .isOptional */
12520},
12521{
12522 UA_TYPENAME("NodesToUnregister") /* .memberName */
12523 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12524 offsetof(UA_UnregisterNodesRequest, nodesToUnregisterSize) - offsetof(UA_UnregisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12525 true, /* .isArray */
12526 false /* .isOptional */
12527},};
12528
12529/* UnregisterNodesResponse */
12530static UA_DataTypeMember UnregisterNodesResponse_members[1] = {
12531{
12532 UA_TYPENAME("ResponseHeader") /* .memberName */
12533 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12534 0, /* .padding */
12535 false, /* .isArray */
12536 false /* .isOptional */
12537},};
12538
12539/* FilterOperator */
12540#define FilterOperator_members NULL
12541
12542/* ContentFilterElement */
12543static UA_DataTypeMember ContentFilterElement_members[2] = {
12544{
12545 UA_TYPENAME("FilterOperator") /* .memberName */
12546 &UA_TYPES[UA_TYPES_FILTEROPERATOR], /* .memberType */
12547 0, /* .padding */
12548 false, /* .isArray */
12549 false /* .isOptional */
12550},
12551{
12552 UA_TYPENAME("FilterOperands") /* .memberName */
12553 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
12554 offsetof(UA_ContentFilterElement, filterOperandsSize) - offsetof(UA_ContentFilterElement, filterOperator) - sizeof(UA_FilterOperator), /* .padding */
12555 true, /* .isArray */
12556 false /* .isOptional */
12557},};
12558
12559/* ContentFilter */
12560static UA_DataTypeMember ContentFilter_members[1] = {
12561{
12562 UA_TYPENAME("Elements") /* .memberName */
12563 &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT], /* .memberType */
12564 0, /* .padding */
12565 true, /* .isArray */
12566 false /* .isOptional */
12567},};
12568
12569/* ElementOperand */
12570static UA_DataTypeMember ElementOperand_members[1] = {
12571{
12572 UA_TYPENAME("Index") /* .memberName */
12573 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12574 0, /* .padding */
12575 false, /* .isArray */
12576 false /* .isOptional */
12577},};
12578
12579/* LiteralOperand */
12580static UA_DataTypeMember LiteralOperand_members[1] = {
12581{
12582 UA_TYPENAME("Value") /* .memberName */
12583 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
12584 0, /* .padding */
12585 false, /* .isArray */
12586 false /* .isOptional */
12587},};
12588
12589/* AttributeOperand */
12590static UA_DataTypeMember AttributeOperand_members[5] = {
12591{
12592 UA_TYPENAME("NodeId") /* .memberName */
12593 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12594 0, /* .padding */
12595 false, /* .isArray */
12596 false /* .isOptional */
12597},
12598{
12599 UA_TYPENAME("Alias") /* .memberName */
12600 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12601 offsetof(UA_AttributeOperand, alias) - offsetof(UA_AttributeOperand, nodeId) - sizeof(UA_NodeId), /* .padding */
12602 false, /* .isArray */
12603 false /* .isOptional */
12604},
12605{
12606 UA_TYPENAME("BrowsePath") /* .memberName */
12607 &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */
12608 offsetof(UA_AttributeOperand, browsePath) - offsetof(UA_AttributeOperand, alias) - sizeof(UA_String), /* .padding */
12609 false, /* .isArray */
12610 false /* .isOptional */
12611},
12612{
12613 UA_TYPENAME("AttributeId") /* .memberName */
12614 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12615 offsetof(UA_AttributeOperand, attributeId) - offsetof(UA_AttributeOperand, browsePath) - sizeof(UA_RelativePath), /* .padding */
12616 false, /* .isArray */
12617 false /* .isOptional */
12618},
12619{
12620 UA_TYPENAME("IndexRange") /* .memberName */
12621 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12622 offsetof(UA_AttributeOperand, indexRange) - offsetof(UA_AttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */
12623 false, /* .isArray */
12624 false /* .isOptional */
12625},};
12626
12627/* SimpleAttributeOperand */
12628static UA_DataTypeMember SimpleAttributeOperand_members[4] = {
12629{
12630 UA_TYPENAME("TypeDefinitionId") /* .memberName */
12631 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12632 0, /* .padding */
12633 false, /* .isArray */
12634 false /* .isOptional */
12635},
12636{
12637 UA_TYPENAME("BrowsePath") /* .memberName */
12638 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12639 offsetof(UA_SimpleAttributeOperand, browsePathSize) - offsetof(UA_SimpleAttributeOperand, typeDefinitionId) - sizeof(UA_NodeId), /* .padding */
12640 true, /* .isArray */
12641 false /* .isOptional */
12642},
12643{
12644 UA_TYPENAME("AttributeId") /* .memberName */
12645 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12646 offsetof(UA_SimpleAttributeOperand, attributeId) - offsetof(UA_SimpleAttributeOperand, browsePath) - sizeof(void *), /* .padding */
12647 false, /* .isArray */
12648 false /* .isOptional */
12649},
12650{
12651 UA_TYPENAME("IndexRange") /* .memberName */
12652 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12653 offsetof(UA_SimpleAttributeOperand, indexRange) - offsetof(UA_SimpleAttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */
12654 false, /* .isArray */
12655 false /* .isOptional */
12656},};
12657
12658/* ContentFilterElementResult */
12659static UA_DataTypeMember ContentFilterElementResult_members[3] = {
12660{
12661 UA_TYPENAME("StatusCode") /* .memberName */
12662 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12663 0, /* .padding */
12664 false, /* .isArray */
12665 false /* .isOptional */
12666},
12667{
12668 UA_TYPENAME("OperandStatusCodes") /* .memberName */
12669 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12670 offsetof(UA_ContentFilterElementResult, operandStatusCodesSize) - offsetof(UA_ContentFilterElementResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
12671 true, /* .isArray */
12672 false /* .isOptional */
12673},
12674{
12675 UA_TYPENAME("OperandDiagnosticInfos") /* .memberName */
12676 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12677 offsetof(UA_ContentFilterElementResult, operandDiagnosticInfosSize) - offsetof(UA_ContentFilterElementResult, operandStatusCodes) - sizeof(void *), /* .padding */
12678 true, /* .isArray */
12679 false /* .isOptional */
12680},};
12681
12682/* ContentFilterResult */
12683static UA_DataTypeMember ContentFilterResult_members[2] = {
12684{
12685 UA_TYPENAME("ElementResults") /* .memberName */
12686 &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT], /* .memberType */
12687 0, /* .padding */
12688 true, /* .isArray */
12689 false /* .isOptional */
12690},
12691{
12692 UA_TYPENAME("ElementDiagnosticInfos") /* .memberName */
12693 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12694 offsetof(UA_ContentFilterResult, elementDiagnosticInfosSize) - offsetof(UA_ContentFilterResult, elementResults) - sizeof(void *), /* .padding */
12695 true, /* .isArray */
12696 false /* .isOptional */
12697},};
12698
12699/* TimestampsToReturn */
12700#define TimestampsToReturn_members NULL
12701
12702/* ReadValueId */
12703static UA_DataTypeMember ReadValueId_members[4] = {
12704{
12705 UA_TYPENAME("NodeId") /* .memberName */
12706 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12707 0, /* .padding */
12708 false, /* .isArray */
12709 false /* .isOptional */
12710},
12711{
12712 UA_TYPENAME("AttributeId") /* .memberName */
12713 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12714 offsetof(UA_ReadValueId, attributeId) - offsetof(UA_ReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */
12715 false, /* .isArray */
12716 false /* .isOptional */
12717},
12718{
12719 UA_TYPENAME("IndexRange") /* .memberName */
12720 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12721 offsetof(UA_ReadValueId, indexRange) - offsetof(UA_ReadValueId, attributeId) - sizeof(UA_UInt32), /* .padding */
12722 false, /* .isArray */
12723 false /* .isOptional */
12724},
12725{
12726 UA_TYPENAME("DataEncoding") /* .memberName */
12727 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12728 offsetof(UA_ReadValueId, dataEncoding) - offsetof(UA_ReadValueId, indexRange) - sizeof(UA_String), /* .padding */
12729 false, /* .isArray */
12730 false /* .isOptional */
12731},};
12732
12733/* ReadRequest */
12734static UA_DataTypeMember ReadRequest_members[4] = {
12735{
12736 UA_TYPENAME("RequestHeader") /* .memberName */
12737 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12738 0, /* .padding */
12739 false, /* .isArray */
12740 false /* .isOptional */
12741},
12742{
12743 UA_TYPENAME("MaxAge") /* .memberName */
12744 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
12745 offsetof(UA_ReadRequest, maxAge) - offsetof(UA_ReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12746 false, /* .isArray */
12747 false /* .isOptional */
12748},
12749{
12750 UA_TYPENAME("TimestampsToReturn") /* .memberName */
12751 &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
12752 offsetof(UA_ReadRequest, timestampsToReturn) - offsetof(UA_ReadRequest, maxAge) - sizeof(UA_Double), /* .padding */
12753 false, /* .isArray */
12754 false /* .isOptional */
12755},
12756{
12757 UA_TYPENAME("NodesToRead") /* .memberName */
12758 &UA_TYPES[UA_TYPES_READVALUEID], /* .memberType */
12759 offsetof(UA_ReadRequest, nodesToReadSize) - offsetof(UA_ReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
12760 true, /* .isArray */
12761 false /* .isOptional */
12762},};
12763
12764/* ReadResponse */
12765static UA_DataTypeMember ReadResponse_members[3] = {
12766{
12767 UA_TYPENAME("ResponseHeader") /* .memberName */
12768 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12769 0, /* .padding */
12770 false, /* .isArray */
12771 false /* .isOptional */
12772},
12773{
12774 UA_TYPENAME("Results") /* .memberName */
12775 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
12776 offsetof(UA_ReadResponse, resultsSize) - offsetof(UA_ReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12777 true, /* .isArray */
12778 false /* .isOptional */
12779},
12780{
12781 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12782 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12783 offsetof(UA_ReadResponse, diagnosticInfosSize) - offsetof(UA_ReadResponse, results) - sizeof(void *), /* .padding */
12784 true, /* .isArray */
12785 false /* .isOptional */
12786},};
12787
12788/* HistoryReadValueId */
12789static UA_DataTypeMember HistoryReadValueId_members[4] = {
12790{
12791 UA_TYPENAME("NodeId") /* .memberName */
12792 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12793 0, /* .padding */
12794 false, /* .isArray */
12795 false /* .isOptional */
12796},
12797{
12798 UA_TYPENAME("IndexRange") /* .memberName */
12799 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12800 offsetof(UA_HistoryReadValueId, indexRange) - offsetof(UA_HistoryReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */
12801 false, /* .isArray */
12802 false /* .isOptional */
12803},
12804{
12805 UA_TYPENAME("DataEncoding") /* .memberName */
12806 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12807 offsetof(UA_HistoryReadValueId, dataEncoding) - offsetof(UA_HistoryReadValueId, indexRange) - sizeof(UA_String), /* .padding */
12808 false, /* .isArray */
12809 false /* .isOptional */
12810},
12811{
12812 UA_TYPENAME("ContinuationPoint") /* .memberName */
12813 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
12814 offsetof(UA_HistoryReadValueId, continuationPoint) - offsetof(UA_HistoryReadValueId, dataEncoding) - sizeof(UA_QualifiedName), /* .padding */
12815 false, /* .isArray */
12816 false /* .isOptional */
12817},};
12818
12819/* HistoryReadResult */
12820static UA_DataTypeMember HistoryReadResult_members[3] = {
12821{
12822 UA_TYPENAME("StatusCode") /* .memberName */
12823 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12824 0, /* .padding */
12825 false, /* .isArray */
12826 false /* .isOptional */
12827},
12828{
12829 UA_TYPENAME("ContinuationPoint") /* .memberName */
12830 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
12831 offsetof(UA_HistoryReadResult, continuationPoint) - offsetof(UA_HistoryReadResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
12832 false, /* .isArray */
12833 false /* .isOptional */
12834},
12835{
12836 UA_TYPENAME("HistoryData") /* .memberName */
12837 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
12838 offsetof(UA_HistoryReadResult, historyData) - offsetof(UA_HistoryReadResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */
12839 false, /* .isArray */
12840 false /* .isOptional */
12841},};
12842
12843/* ReadRawModifiedDetails */
12844static UA_DataTypeMember ReadRawModifiedDetails_members[5] = {
12845{
12846 UA_TYPENAME("IsReadModified") /* .memberName */
12847 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12848 0, /* .padding */
12849 false, /* .isArray */
12850 false /* .isOptional */
12851},
12852{
12853 UA_TYPENAME("StartTime") /* .memberName */
12854 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
12855 offsetof(UA_ReadRawModifiedDetails, startTime) - offsetof(UA_ReadRawModifiedDetails, isReadModified) - sizeof(UA_Boolean), /* .padding */
12856 false, /* .isArray */
12857 false /* .isOptional */
12858},
12859{
12860 UA_TYPENAME("EndTime") /* .memberName */
12861 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
12862 offsetof(UA_ReadRawModifiedDetails, endTime) - offsetof(UA_ReadRawModifiedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
12863 false, /* .isArray */
12864 false /* .isOptional */
12865},
12866{
12867 UA_TYPENAME("NumValuesPerNode") /* .memberName */
12868 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12869 offsetof(UA_ReadRawModifiedDetails, numValuesPerNode) - offsetof(UA_ReadRawModifiedDetails, endTime) - sizeof(UA_DateTime), /* .padding */
12870 false, /* .isArray */
12871 false /* .isOptional */
12872},
12873{
12874 UA_TYPENAME("ReturnBounds") /* .memberName */
12875 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12876 offsetof(UA_ReadRawModifiedDetails, returnBounds) - offsetof(UA_ReadRawModifiedDetails, numValuesPerNode) - sizeof(UA_UInt32), /* .padding */
12877 false, /* .isArray */
12878 false /* .isOptional */
12879},};
12880
12881/* ReadAtTimeDetails */
12882static UA_DataTypeMember ReadAtTimeDetails_members[2] = {
12883{
12884 UA_TYPENAME("ReqTimes") /* .memberName */
12885 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
12886 0, /* .padding */
12887 true, /* .isArray */
12888 false /* .isOptional */
12889},
12890{
12891 UA_TYPENAME("UseSimpleBounds") /* .memberName */
12892 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12893 offsetof(UA_ReadAtTimeDetails, useSimpleBounds) - offsetof(UA_ReadAtTimeDetails, reqTimes) - sizeof(void *), /* .padding */
12894 false, /* .isArray */
12895 false /* .isOptional */
12896},};
12897
12898/* HistoryData */
12899static UA_DataTypeMember HistoryData_members[1] = {
12900{
12901 UA_TYPENAME("DataValues") /* .memberName */
12902 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
12903 0, /* .padding */
12904 true, /* .isArray */
12905 false /* .isOptional */
12906},};
12907
12908/* HistoryReadRequest */
12909static UA_DataTypeMember HistoryReadRequest_members[5] = {
12910{
12911 UA_TYPENAME("RequestHeader") /* .memberName */
12912 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12913 0, /* .padding */
12914 false, /* .isArray */
12915 false /* .isOptional */
12916},
12917{
12918 UA_TYPENAME("HistoryReadDetails") /* .memberName */
12919 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
12920 offsetof(UA_HistoryReadRequest, historyReadDetails) - offsetof(UA_HistoryReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12921 false, /* .isArray */
12922 false /* .isOptional */
12923},
12924{
12925 UA_TYPENAME("TimestampsToReturn") /* .memberName */
12926 &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
12927 offsetof(UA_HistoryReadRequest, timestampsToReturn) - offsetof(UA_HistoryReadRequest, historyReadDetails) - sizeof(UA_ExtensionObject), /* .padding */
12928 false, /* .isArray */
12929 false /* .isOptional */
12930},
12931{
12932 UA_TYPENAME("ReleaseContinuationPoints") /* .memberName */
12933 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12934 offsetof(UA_HistoryReadRequest, releaseContinuationPoints) - offsetof(UA_HistoryReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
12935 false, /* .isArray */
12936 false /* .isOptional */
12937},
12938{
12939 UA_TYPENAME("NodesToRead") /* .memberName */
12940 &UA_TYPES[UA_TYPES_HISTORYREADVALUEID], /* .memberType */
12941 offsetof(UA_HistoryReadRequest, nodesToReadSize) - offsetof(UA_HistoryReadRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */
12942 true, /* .isArray */
12943 false /* .isOptional */
12944},};
12945
12946/* HistoryReadResponse */
12947static UA_DataTypeMember HistoryReadResponse_members[3] = {
12948{
12949 UA_TYPENAME("ResponseHeader") /* .memberName */
12950 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12951 0, /* .padding */
12952 false, /* .isArray */
12953 false /* .isOptional */
12954},
12955{
12956 UA_TYPENAME("Results") /* .memberName */
12957 &UA_TYPES[UA_TYPES_HISTORYREADRESULT], /* .memberType */
12958 offsetof(UA_HistoryReadResponse, resultsSize) - offsetof(UA_HistoryReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12959 true, /* .isArray */
12960 false /* .isOptional */
12961},
12962{
12963 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12964 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12965 offsetof(UA_HistoryReadResponse, diagnosticInfosSize) - offsetof(UA_HistoryReadResponse, results) - sizeof(void *), /* .padding */
12966 true, /* .isArray */
12967 false /* .isOptional */
12968},};
12969
12970/* WriteValue */
12971static UA_DataTypeMember WriteValue_members[4] = {
12972{
12973 UA_TYPENAME("NodeId") /* .memberName */
12974 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12975 0, /* .padding */
12976 false, /* .isArray */
12977 false /* .isOptional */
12978},
12979{
12980 UA_TYPENAME("AttributeId") /* .memberName */
12981 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12982 offsetof(UA_WriteValue, attributeId) - offsetof(UA_WriteValue, nodeId) - sizeof(UA_NodeId), /* .padding */
12983 false, /* .isArray */
12984 false /* .isOptional */
12985},
12986{
12987 UA_TYPENAME("IndexRange") /* .memberName */
12988 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12989 offsetof(UA_WriteValue, indexRange) - offsetof(UA_WriteValue, attributeId) - sizeof(UA_UInt32), /* .padding */
12990 false, /* .isArray */
12991 false /* .isOptional */
12992},
12993{
12994 UA_TYPENAME("Value") /* .memberName */
12995 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
12996 offsetof(UA_WriteValue, value) - offsetof(UA_WriteValue, indexRange) - sizeof(UA_String), /* .padding */
12997 false, /* .isArray */
12998 false /* .isOptional */
12999},};
13000
13001/* WriteRequest */
13002static UA_DataTypeMember WriteRequest_members[2] = {
13003{
13004 UA_TYPENAME("RequestHeader") /* .memberName */
13005 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13006 0, /* .padding */
13007 false, /* .isArray */
13008 false /* .isOptional */
13009},
13010{
13011 UA_TYPENAME("NodesToWrite") /* .memberName */
13012 &UA_TYPES[UA_TYPES_WRITEVALUE], /* .memberType */
13013 offsetof(UA_WriteRequest, nodesToWriteSize) - offsetof(UA_WriteRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13014 true, /* .isArray */
13015 false /* .isOptional */
13016},};
13017
13018/* WriteResponse */
13019static UA_DataTypeMember WriteResponse_members[3] = {
13020{
13021 UA_TYPENAME("ResponseHeader") /* .memberName */
13022 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13023 0, /* .padding */
13024 false, /* .isArray */
13025 false /* .isOptional */
13026},
13027{
13028 UA_TYPENAME("Results") /* .memberName */
13029 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13030 offsetof(UA_WriteResponse, resultsSize) - offsetof(UA_WriteResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13031 true, /* .isArray */
13032 false /* .isOptional */
13033},
13034{
13035 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13036 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13037 offsetof(UA_WriteResponse, diagnosticInfosSize) - offsetof(UA_WriteResponse, results) - sizeof(void *), /* .padding */
13038 true, /* .isArray */
13039 false /* .isOptional */
13040},};
13041
13042/* HistoryUpdateType */
13043#define HistoryUpdateType_members NULL
13044
13045/* PerformUpdateType */
13046#define PerformUpdateType_members NULL
13047
13048/* UpdateDataDetails */
13049static UA_DataTypeMember UpdateDataDetails_members[3] = {
13050{
13051 UA_TYPENAME("NodeId") /* .memberName */
13052 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13053 0, /* .padding */
13054 false, /* .isArray */
13055 false /* .isOptional */
13056},
13057{
13058 UA_TYPENAME("PerformInsertReplace") /* .memberName */
13059 &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE], /* .memberType */
13060 offsetof(UA_UpdateDataDetails, performInsertReplace) - offsetof(UA_UpdateDataDetails, nodeId) - sizeof(UA_NodeId), /* .padding */
13061 false, /* .isArray */
13062 false /* .isOptional */
13063},
13064{
13065 UA_TYPENAME("UpdateValues") /* .memberName */
13066 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
13067 offsetof(UA_UpdateDataDetails, updateValuesSize) - offsetof(UA_UpdateDataDetails, performInsertReplace) - sizeof(UA_PerformUpdateType), /* .padding */
13068 true, /* .isArray */
13069 false /* .isOptional */
13070},};
13071
13072/* DeleteRawModifiedDetails */
13073static UA_DataTypeMember DeleteRawModifiedDetails_members[4] = {
13074{
13075 UA_TYPENAME("NodeId") /* .memberName */
13076 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13077 0, /* .padding */
13078 false, /* .isArray */
13079 false /* .isOptional */
13080},
13081{
13082 UA_TYPENAME("IsDeleteModified") /* .memberName */
13083 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13084 offsetof(UA_DeleteRawModifiedDetails, isDeleteModified) - offsetof(UA_DeleteRawModifiedDetails, nodeId) - sizeof(UA_NodeId), /* .padding */
13085 false, /* .isArray */
13086 false /* .isOptional */
13087},
13088{
13089 UA_TYPENAME("StartTime") /* .memberName */
13090 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
13091 offsetof(UA_DeleteRawModifiedDetails, startTime) - offsetof(UA_DeleteRawModifiedDetails, isDeleteModified) - sizeof(UA_Boolean), /* .padding */
13092 false, /* .isArray */
13093 false /* .isOptional */
13094},
13095{
13096 UA_TYPENAME("EndTime") /* .memberName */
13097 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
13098 offsetof(UA_DeleteRawModifiedDetails, endTime) - offsetof(UA_DeleteRawModifiedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
13099 false, /* .isArray */
13100 false /* .isOptional */
13101},};
13102
13103/* HistoryUpdateResult */
13104static UA_DataTypeMember HistoryUpdateResult_members[3] = {
13105{
13106 UA_TYPENAME("StatusCode") /* .memberName */
13107 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13108 0, /* .padding */
13109 false, /* .isArray */
13110 false /* .isOptional */
13111},
13112{
13113 UA_TYPENAME("OperationResults") /* .memberName */
13114 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13115 offsetof(UA_HistoryUpdateResult, operationResultsSize) - offsetof(UA_HistoryUpdateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
13116 true, /* .isArray */
13117 false /* .isOptional */
13118},
13119{
13120 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13121 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13122 offsetof(UA_HistoryUpdateResult, diagnosticInfosSize) - offsetof(UA_HistoryUpdateResult, operationResults) - sizeof(void *), /* .padding */
13123 true, /* .isArray */
13124 false /* .isOptional */
13125},};
13126
13127/* HistoryUpdateRequest */
13128static UA_DataTypeMember HistoryUpdateRequest_members[2] = {
13129{
13130 UA_TYPENAME("RequestHeader") /* .memberName */
13131 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13132 0, /* .padding */
13133 false, /* .isArray */
13134 false /* .isOptional */
13135},
13136{
13137 UA_TYPENAME("HistoryUpdateDetails") /* .memberName */
13138 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
13139 offsetof(UA_HistoryUpdateRequest, historyUpdateDetailsSize) - offsetof(UA_HistoryUpdateRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13140 true, /* .isArray */
13141 false /* .isOptional */
13142},};
13143
13144/* HistoryUpdateResponse */
13145static UA_DataTypeMember HistoryUpdateResponse_members[3] = {
13146{
13147 UA_TYPENAME("ResponseHeader") /* .memberName */
13148 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13149 0, /* .padding */
13150 false, /* .isArray */
13151 false /* .isOptional */
13152},
13153{
13154 UA_TYPENAME("Results") /* .memberName */
13155 &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT], /* .memberType */
13156 offsetof(UA_HistoryUpdateResponse, resultsSize) - offsetof(UA_HistoryUpdateResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13157 true, /* .isArray */
13158 false /* .isOptional */
13159},
13160{
13161 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13162 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13163 offsetof(UA_HistoryUpdateResponse, diagnosticInfosSize) - offsetof(UA_HistoryUpdateResponse, results) - sizeof(void *), /* .padding */
13164 true, /* .isArray */
13165 false /* .isOptional */
13166},};
13167
13168/* CallMethodRequest */
13169static UA_DataTypeMember CallMethodRequest_members[3] = {
13170{
13171 UA_TYPENAME("ObjectId") /* .memberName */
13172 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13173 0, /* .padding */
13174 false, /* .isArray */
13175 false /* .isOptional */
13176},
13177{
13178 UA_TYPENAME("MethodId") /* .memberName */
13179 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13180 offsetof(UA_CallMethodRequest, methodId) - offsetof(UA_CallMethodRequest, objectId) - sizeof(UA_NodeId), /* .padding */
13181 false, /* .isArray */
13182 false /* .isOptional */
13183},
13184{
13185 UA_TYPENAME("InputArguments") /* .memberName */
13186 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
13187 offsetof(UA_CallMethodRequest, inputArgumentsSize) - offsetof(UA_CallMethodRequest, methodId) - sizeof(UA_NodeId), /* .padding */
13188 true, /* .isArray */
13189 false /* .isOptional */
13190},};
13191
13192/* CallMethodResult */
13193static UA_DataTypeMember CallMethodResult_members[4] = {
13194{
13195 UA_TYPENAME("StatusCode") /* .memberName */
13196 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13197 0, /* .padding */
13198 false, /* .isArray */
13199 false /* .isOptional */
13200},
13201{
13202 UA_TYPENAME("InputArgumentResults") /* .memberName */
13203 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13204 offsetof(UA_CallMethodResult, inputArgumentResultsSize) - offsetof(UA_CallMethodResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
13205 true, /* .isArray */
13206 false /* .isOptional */
13207},
13208{
13209 UA_TYPENAME("InputArgumentDiagnosticInfos") /* .memberName */
13210 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13211 offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfosSize) - offsetof(UA_CallMethodResult, inputArgumentResults) - sizeof(void *), /* .padding */
13212 true, /* .isArray */
13213 false /* .isOptional */
13214},
13215{
13216 UA_TYPENAME("OutputArguments") /* .memberName */
13217 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
13218 offsetof(UA_CallMethodResult, outputArgumentsSize) - offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfos) - sizeof(void *), /* .padding */
13219 true, /* .isArray */
13220 false /* .isOptional */
13221},};
13222
13223/* CallRequest */
13224static UA_DataTypeMember CallRequest_members[2] = {
13225{
13226 UA_TYPENAME("RequestHeader") /* .memberName */
13227 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13228 0, /* .padding */
13229 false, /* .isArray */
13230 false /* .isOptional */
13231},
13232{
13233 UA_TYPENAME("MethodsToCall") /* .memberName */
13234 &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], /* .memberType */
13235 offsetof(UA_CallRequest, methodsToCallSize) - offsetof(UA_CallRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13236 true, /* .isArray */
13237 false /* .isOptional */
13238},};
13239
13240/* CallResponse */
13241static UA_DataTypeMember CallResponse_members[3] = {
13242{
13243 UA_TYPENAME("ResponseHeader") /* .memberName */
13244 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13245 0, /* .padding */
13246 false, /* .isArray */
13247 false /* .isOptional */
13248},
13249{
13250 UA_TYPENAME("Results") /* .memberName */
13251 &UA_TYPES[UA_TYPES_CALLMETHODRESULT], /* .memberType */
13252 offsetof(UA_CallResponse, resultsSize) - offsetof(UA_CallResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13253 true, /* .isArray */
13254 false /* .isOptional */
13255},
13256{
13257 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13258 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13259 offsetof(UA_CallResponse, diagnosticInfosSize) - offsetof(UA_CallResponse, results) - sizeof(void *), /* .padding */
13260 true, /* .isArray */
13261 false /* .isOptional */
13262},};
13263
13264/* MonitoringMode */
13265#define MonitoringMode_members NULL
13266
13267/* DataChangeTrigger */
13268#define DataChangeTrigger_members NULL
13269
13270/* DeadbandType */
13271#define DeadbandType_members NULL
13272
13273/* DataChangeFilter */
13274static UA_DataTypeMember DataChangeFilter_members[3] = {
13275{
13276 UA_TYPENAME("Trigger") /* .memberName */
13277 &UA_TYPES[UA_TYPES_DATACHANGETRIGGER], /* .memberType */
13278 0, /* .padding */
13279 false, /* .isArray */
13280 false /* .isOptional */
13281},
13282{
13283 UA_TYPENAME("DeadbandType") /* .memberName */
13284 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13285 offsetof(UA_DataChangeFilter, deadbandType) - offsetof(UA_DataChangeFilter, trigger) - sizeof(UA_DataChangeTrigger), /* .padding */
13286 false, /* .isArray */
13287 false /* .isOptional */
13288},
13289{
13290 UA_TYPENAME("DeadbandValue") /* .memberName */
13291 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13292 offsetof(UA_DataChangeFilter, deadbandValue) - offsetof(UA_DataChangeFilter, deadbandType) - sizeof(UA_UInt32), /* .padding */
13293 false, /* .isArray */
13294 false /* .isOptional */
13295},};
13296
13297/* EventFilter */
13298static UA_DataTypeMember EventFilter_members[2] = {
13299{
13300 UA_TYPENAME("SelectClauses") /* .memberName */
13301 &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND], /* .memberType */
13302 0, /* .padding */
13303 true, /* .isArray */
13304 false /* .isOptional */
13305},
13306{
13307 UA_TYPENAME("WhereClause") /* .memberName */
13308 &UA_TYPES[UA_TYPES_CONTENTFILTER], /* .memberType */
13309 offsetof(UA_EventFilter, whereClause) - offsetof(UA_EventFilter, selectClauses) - sizeof(void *), /* .padding */
13310 false, /* .isArray */
13311 false /* .isOptional */
13312},};
13313
13314/* AggregateConfiguration */
13315static UA_DataTypeMember AggregateConfiguration_members[5] = {
13316{
13317 UA_TYPENAME("UseServerCapabilitiesDefaults") /* .memberName */
13318 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13319 0, /* .padding */
13320 false, /* .isArray */
13321 false /* .isOptional */
13322},
13323{
13324 UA_TYPENAME("TreatUncertainAsBad") /* .memberName */
13325 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13326 offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - offsetof(UA_AggregateConfiguration, useServerCapabilitiesDefaults) - sizeof(UA_Boolean), /* .padding */
13327 false, /* .isArray */
13328 false /* .isOptional */
13329},
13330{
13331 UA_TYPENAME("PercentDataBad") /* .memberName */
13332 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
13333 offsetof(UA_AggregateConfiguration, percentDataBad) - offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - sizeof(UA_Boolean), /* .padding */
13334 false, /* .isArray */
13335 false /* .isOptional */
13336},
13337{
13338 UA_TYPENAME("PercentDataGood") /* .memberName */
13339 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
13340 offsetof(UA_AggregateConfiguration, percentDataGood) - offsetof(UA_AggregateConfiguration, percentDataBad) - sizeof(UA_Byte), /* .padding */
13341 false, /* .isArray */
13342 false /* .isOptional */
13343},
13344{
13345 UA_TYPENAME("UseSlopedExtrapolation") /* .memberName */
13346 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13347 offsetof(UA_AggregateConfiguration, useSlopedExtrapolation) - offsetof(UA_AggregateConfiguration, percentDataGood) - sizeof(UA_Byte), /* .padding */
13348 false, /* .isArray */
13349 false /* .isOptional */
13350},};
13351
13352/* AggregateFilter */
13353static UA_DataTypeMember AggregateFilter_members[4] = {
13354{
13355 UA_TYPENAME("StartTime") /* .memberName */
13356 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
13357 0, /* .padding */
13358 false, /* .isArray */
13359 false /* .isOptional */
13360},
13361{
13362 UA_TYPENAME("AggregateType") /* .memberName */
13363 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13364 offsetof(UA_AggregateFilter, aggregateType) - offsetof(UA_AggregateFilter, startTime) - sizeof(UA_DateTime), /* .padding */
13365 false, /* .isArray */
13366 false /* .isOptional */
13367},
13368{
13369 UA_TYPENAME("ProcessingInterval") /* .memberName */
13370 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13371 offsetof(UA_AggregateFilter, processingInterval) - offsetof(UA_AggregateFilter, aggregateType) - sizeof(UA_NodeId), /* .padding */
13372 false, /* .isArray */
13373 false /* .isOptional */
13374},
13375{
13376 UA_TYPENAME("AggregateConfiguration") /* .memberName */
13377 &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */
13378 offsetof(UA_AggregateFilter, aggregateConfiguration) - offsetof(UA_AggregateFilter, processingInterval) - sizeof(UA_Double), /* .padding */
13379 false, /* .isArray */
13380 false /* .isOptional */
13381},};
13382
13383/* EventFilterResult */
13384static UA_DataTypeMember EventFilterResult_members[3] = {
13385{
13386 UA_TYPENAME("SelectClauseResults") /* .memberName */
13387 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13388 0, /* .padding */
13389 true, /* .isArray */
13390 false /* .isOptional */
13391},
13392{
13393 UA_TYPENAME("SelectClauseDiagnosticInfos") /* .memberName */
13394 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13395 offsetof(UA_EventFilterResult, selectClauseDiagnosticInfosSize) - offsetof(UA_EventFilterResult, selectClauseResults) - sizeof(void *), /* .padding */
13396 true, /* .isArray */
13397 false /* .isOptional */
13398},
13399{
13400 UA_TYPENAME("WhereClauseResult") /* .memberName */
13401 &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT], /* .memberType */
13402 offsetof(UA_EventFilterResult, whereClauseResult) - offsetof(UA_EventFilterResult, selectClauseDiagnosticInfos) - sizeof(void *), /* .padding */
13403 false, /* .isArray */
13404 false /* .isOptional */
13405},};
13406
13407/* MonitoringParameters */
13408static UA_DataTypeMember MonitoringParameters_members[5] = {
13409{
13410 UA_TYPENAME("ClientHandle") /* .memberName */
13411 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13412 0, /* .padding */
13413 false, /* .isArray */
13414 false /* .isOptional */
13415},
13416{
13417 UA_TYPENAME("SamplingInterval") /* .memberName */
13418 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13419 offsetof(UA_MonitoringParameters, samplingInterval) - offsetof(UA_MonitoringParameters, clientHandle) - sizeof(UA_UInt32), /* .padding */
13420 false, /* .isArray */
13421 false /* .isOptional */
13422},
13423{
13424 UA_TYPENAME("Filter") /* .memberName */
13425 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
13426 offsetof(UA_MonitoringParameters, filter) - offsetof(UA_MonitoringParameters, samplingInterval) - sizeof(UA_Double), /* .padding */
13427 false, /* .isArray */
13428 false /* .isOptional */
13429},
13430{
13431 UA_TYPENAME("QueueSize") /* .memberName */
13432 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13433 offsetof(UA_MonitoringParameters, queueSize) - offsetof(UA_MonitoringParameters, filter) - sizeof(UA_ExtensionObject), /* .padding */
13434 false, /* .isArray */
13435 false /* .isOptional */
13436},
13437{
13438 UA_TYPENAME("DiscardOldest") /* .memberName */
13439 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13440 offsetof(UA_MonitoringParameters, discardOldest) - offsetof(UA_MonitoringParameters, queueSize) - sizeof(UA_UInt32), /* .padding */
13441 false, /* .isArray */
13442 false /* .isOptional */
13443},};
13444
13445/* MonitoredItemCreateRequest */
13446static UA_DataTypeMember MonitoredItemCreateRequest_members[3] = {
13447{
13448 UA_TYPENAME("ItemToMonitor") /* .memberName */
13449 &UA_TYPES[UA_TYPES_READVALUEID], /* .memberType */
13450 0, /* .padding */
13451 false, /* .isArray */
13452 false /* .isOptional */
13453},
13454{
13455 UA_TYPENAME("MonitoringMode") /* .memberName */
13456 &UA_TYPES[UA_TYPES_MONITORINGMODE], /* .memberType */
13457 offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - offsetof(UA_MonitoredItemCreateRequest, itemToMonitor) - sizeof(UA_ReadValueId), /* .padding */
13458 false, /* .isArray */
13459 false /* .isOptional */
13460},
13461{
13462 UA_TYPENAME("RequestedParameters") /* .memberName */
13463 &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], /* .memberType */
13464 offsetof(UA_MonitoredItemCreateRequest, requestedParameters) - offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */
13465 false, /* .isArray */
13466 false /* .isOptional */
13467},};
13468
13469/* MonitoredItemCreateResult */
13470static UA_DataTypeMember MonitoredItemCreateResult_members[5] = {
13471{
13472 UA_TYPENAME("StatusCode") /* .memberName */
13473 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13474 0, /* .padding */
13475 false, /* .isArray */
13476 false /* .isOptional */
13477},
13478{
13479 UA_TYPENAME("MonitoredItemId") /* .memberName */
13480 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13481 offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - offsetof(UA_MonitoredItemCreateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
13482 false, /* .isArray */
13483 false /* .isOptional */
13484},
13485{
13486 UA_TYPENAME("RevisedSamplingInterval") /* .memberName */
13487 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13488 offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - sizeof(UA_UInt32), /* .padding */
13489 false, /* .isArray */
13490 false /* .isOptional */
13491},
13492{
13493 UA_TYPENAME("RevisedQueueSize") /* .memberName */
13494 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13495 offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */
13496 false, /* .isArray */
13497 false /* .isOptional */
13498},
13499{
13500 UA_TYPENAME("FilterResult") /* .memberName */
13501 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
13502 offsetof(UA_MonitoredItemCreateResult, filterResult) - offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */
13503 false, /* .isArray */
13504 false /* .isOptional */
13505},};
13506
13507/* CreateMonitoredItemsRequest */
13508static UA_DataTypeMember CreateMonitoredItemsRequest_members[4] = {
13509{
13510 UA_TYPENAME("RequestHeader") /* .memberName */
13511 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13512 0, /* .padding */
13513 false, /* .isArray */
13514 false /* .isOptional */
13515},
13516{
13517 UA_TYPENAME("SubscriptionId") /* .memberName */
13518 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13519 offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - offsetof(UA_CreateMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13520 false, /* .isArray */
13521 false /* .isOptional */
13522},
13523{
13524 UA_TYPENAME("TimestampsToReturn") /* .memberName */
13525 &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
13526 offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13527 false, /* .isArray */
13528 false /* .isOptional */
13529},
13530{
13531 UA_TYPENAME("ItemsToCreate") /* .memberName */
13532 &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST], /* .memberType */
13533 offsetof(UA_CreateMonitoredItemsRequest, itemsToCreateSize) - offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
13534 true, /* .isArray */
13535 false /* .isOptional */
13536},};
13537
13538/* CreateMonitoredItemsResponse */
13539static UA_DataTypeMember CreateMonitoredItemsResponse_members[3] = {
13540{
13541 UA_TYPENAME("ResponseHeader") /* .memberName */
13542 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13543 0, /* .padding */
13544 false, /* .isArray */
13545 false /* .isOptional */
13546},
13547{
13548 UA_TYPENAME("Results") /* .memberName */
13549 &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT], /* .memberType */
13550 offsetof(UA_CreateMonitoredItemsResponse, resultsSize) - offsetof(UA_CreateMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13551 true, /* .isArray */
13552 false /* .isOptional */
13553},
13554{
13555 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13556 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13557 offsetof(UA_CreateMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_CreateMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
13558 true, /* .isArray */
13559 false /* .isOptional */
13560},};
13561
13562/* MonitoredItemModifyRequest */
13563static UA_DataTypeMember MonitoredItemModifyRequest_members[2] = {
13564{
13565 UA_TYPENAME("MonitoredItemId") /* .memberName */
13566 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13567 0, /* .padding */
13568 false, /* .isArray */
13569 false /* .isOptional */
13570},
13571{
13572 UA_TYPENAME("RequestedParameters") /* .memberName */
13573 &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], /* .memberType */
13574 offsetof(UA_MonitoredItemModifyRequest, requestedParameters) - offsetof(UA_MonitoredItemModifyRequest, monitoredItemId) - sizeof(UA_UInt32), /* .padding */
13575 false, /* .isArray */
13576 false /* .isOptional */
13577},};
13578
13579/* MonitoredItemModifyResult */
13580static UA_DataTypeMember MonitoredItemModifyResult_members[4] = {
13581{
13582 UA_TYPENAME("StatusCode") /* .memberName */
13583 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13584 0, /* .padding */
13585 false, /* .isArray */
13586 false /* .isOptional */
13587},
13588{
13589 UA_TYPENAME("RevisedSamplingInterval") /* .memberName */
13590 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13591 offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemModifyResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
13592 false, /* .isArray */
13593 false /* .isOptional */
13594},
13595{
13596 UA_TYPENAME("RevisedQueueSize") /* .memberName */
13597 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13598 offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */
13599 false, /* .isArray */
13600 false /* .isOptional */
13601},
13602{
13603 UA_TYPENAME("FilterResult") /* .memberName */
13604 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
13605 offsetof(UA_MonitoredItemModifyResult, filterResult) - offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */
13606 false, /* .isArray */
13607 false /* .isOptional */
13608},};
13609
13610/* ModifyMonitoredItemsRequest */
13611static UA_DataTypeMember ModifyMonitoredItemsRequest_members[4] = {
13612{
13613 UA_TYPENAME("RequestHeader") /* .memberName */
13614 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13615 0, /* .padding */
13616 false, /* .isArray */
13617 false /* .isOptional */
13618},
13619{
13620 UA_TYPENAME("SubscriptionId") /* .memberName */
13621 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13622 offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - offsetof(UA_ModifyMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13623 false, /* .isArray */
13624 false /* .isOptional */
13625},
13626{
13627 UA_TYPENAME("TimestampsToReturn") /* .memberName */
13628 &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
13629 offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13630 false, /* .isArray */
13631 false /* .isOptional */
13632},
13633{
13634 UA_TYPENAME("ItemsToModify") /* .memberName */
13635 &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST], /* .memberType */
13636 offsetof(UA_ModifyMonitoredItemsRequest, itemsToModifySize) - offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
13637 true, /* .isArray */
13638 false /* .isOptional */
13639},};
13640
13641/* ModifyMonitoredItemsResponse */
13642static UA_DataTypeMember ModifyMonitoredItemsResponse_members[3] = {
13643{
13644 UA_TYPENAME("ResponseHeader") /* .memberName */
13645 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13646 0, /* .padding */
13647 false, /* .isArray */
13648 false /* .isOptional */
13649},
13650{
13651 UA_TYPENAME("Results") /* .memberName */
13652 &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT], /* .memberType */
13653 offsetof(UA_ModifyMonitoredItemsResponse, resultsSize) - offsetof(UA_ModifyMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13654 true, /* .isArray */
13655 false /* .isOptional */
13656},
13657{
13658 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13659 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13660 offsetof(UA_ModifyMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_ModifyMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
13661 true, /* .isArray */
13662 false /* .isOptional */
13663},};
13664
13665/* SetMonitoringModeRequest */
13666static UA_DataTypeMember SetMonitoringModeRequest_members[4] = {
13667{
13668 UA_TYPENAME("RequestHeader") /* .memberName */
13669 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13670 0, /* .padding */
13671 false, /* .isArray */
13672 false /* .isOptional */
13673},
13674{
13675 UA_TYPENAME("SubscriptionId") /* .memberName */
13676 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13677 offsetof(UA_SetMonitoringModeRequest, subscriptionId) - offsetof(UA_SetMonitoringModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13678 false, /* .isArray */
13679 false /* .isOptional */
13680},
13681{
13682 UA_TYPENAME("MonitoringMode") /* .memberName */
13683 &UA_TYPES[UA_TYPES_MONITORINGMODE], /* .memberType */
13684 offsetof(UA_SetMonitoringModeRequest, monitoringMode) - offsetof(UA_SetMonitoringModeRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13685 false, /* .isArray */
13686 false /* .isOptional */
13687},
13688{
13689 UA_TYPENAME("MonitoredItemIds") /* .memberName */
13690 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13691 offsetof(UA_SetMonitoringModeRequest, monitoredItemIdsSize) - offsetof(UA_SetMonitoringModeRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */
13692 true, /* .isArray */
13693 false /* .isOptional */
13694},};
13695
13696/* SetMonitoringModeResponse */
13697static UA_DataTypeMember SetMonitoringModeResponse_members[3] = {
13698{
13699 UA_TYPENAME("ResponseHeader") /* .memberName */
13700 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13701 0, /* .padding */
13702 false, /* .isArray */
13703 false /* .isOptional */
13704},
13705{
13706 UA_TYPENAME("Results") /* .memberName */
13707 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13708 offsetof(UA_SetMonitoringModeResponse, resultsSize) - offsetof(UA_SetMonitoringModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13709 true, /* .isArray */
13710 false /* .isOptional */
13711},
13712{
13713 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13714 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13715 offsetof(UA_SetMonitoringModeResponse, diagnosticInfosSize) - offsetof(UA_SetMonitoringModeResponse, results) - sizeof(void *), /* .padding */
13716 true, /* .isArray */
13717 false /* .isOptional */
13718},};
13719
13720/* SetTriggeringRequest */
13721static UA_DataTypeMember SetTriggeringRequest_members[5] = {
13722{
13723 UA_TYPENAME("RequestHeader") /* .memberName */
13724 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13725 0, /* .padding */
13726 false, /* .isArray */
13727 false /* .isOptional */
13728},
13729{
13730 UA_TYPENAME("SubscriptionId") /* .memberName */
13731 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13732 offsetof(UA_SetTriggeringRequest, subscriptionId) - offsetof(UA_SetTriggeringRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13733 false, /* .isArray */
13734 false /* .isOptional */
13735},
13736{
13737 UA_TYPENAME("TriggeringItemId") /* .memberName */
13738 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13739 offsetof(UA_SetTriggeringRequest, triggeringItemId) - offsetof(UA_SetTriggeringRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13740 false, /* .isArray */
13741 false /* .isOptional */
13742},
13743{
13744 UA_TYPENAME("LinksToAdd") /* .memberName */
13745 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13746 offsetof(UA_SetTriggeringRequest, linksToAddSize) - offsetof(UA_SetTriggeringRequest, triggeringItemId) - sizeof(UA_UInt32), /* .padding */
13747 true, /* .isArray */
13748 false /* .isOptional */
13749},
13750{
13751 UA_TYPENAME("LinksToRemove") /* .memberName */
13752 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13753 offsetof(UA_SetTriggeringRequest, linksToRemoveSize) - offsetof(UA_SetTriggeringRequest, linksToAdd) - sizeof(void *), /* .padding */
13754 true, /* .isArray */
13755 false /* .isOptional */
13756},};
13757
13758/* SetTriggeringResponse */
13759static UA_DataTypeMember SetTriggeringResponse_members[5] = {
13760{
13761 UA_TYPENAME("ResponseHeader") /* .memberName */
13762 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13763 0, /* .padding */
13764 false, /* .isArray */
13765 false /* .isOptional */
13766},
13767{
13768 UA_TYPENAME("AddResults") /* .memberName */
13769 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13770 offsetof(UA_SetTriggeringResponse, addResultsSize) - offsetof(UA_SetTriggeringResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13771 true, /* .isArray */
13772 false /* .isOptional */
13773},
13774{
13775 UA_TYPENAME("AddDiagnosticInfos") /* .memberName */
13776 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13777 offsetof(UA_SetTriggeringResponse, addDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, addResults) - sizeof(void *), /* .padding */
13778 true, /* .isArray */
13779 false /* .isOptional */
13780},
13781{
13782 UA_TYPENAME("RemoveResults") /* .memberName */
13783 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13784 offsetof(UA_SetTriggeringResponse, removeResultsSize) - offsetof(UA_SetTriggeringResponse, addDiagnosticInfos) - sizeof(void *), /* .padding */
13785 true, /* .isArray */
13786 false /* .isOptional */
13787},
13788{
13789 UA_TYPENAME("RemoveDiagnosticInfos") /* .memberName */
13790 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13791 offsetof(UA_SetTriggeringResponse, removeDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, removeResults) - sizeof(void *), /* .padding */
13792 true, /* .isArray */
13793 false /* .isOptional */
13794},};
13795
13796/* DeleteMonitoredItemsRequest */
13797static UA_DataTypeMember DeleteMonitoredItemsRequest_members[3] = {
13798{
13799 UA_TYPENAME("RequestHeader") /* .memberName */
13800 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13801 0, /* .padding */
13802 false, /* .isArray */
13803 false /* .isOptional */
13804},
13805{
13806 UA_TYPENAME("SubscriptionId") /* .memberName */
13807 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13808 offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - offsetof(UA_DeleteMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13809 false, /* .isArray */
13810 false /* .isOptional */
13811},
13812{
13813 UA_TYPENAME("MonitoredItemIds") /* .memberName */
13814 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13815 offsetof(UA_DeleteMonitoredItemsRequest, monitoredItemIdsSize) - offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13816 true, /* .isArray */
13817 false /* .isOptional */
13818},};
13819
13820/* DeleteMonitoredItemsResponse */
13821static UA_DataTypeMember DeleteMonitoredItemsResponse_members[3] = {
13822{
13823 UA_TYPENAME("ResponseHeader") /* .memberName */
13824 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13825 0, /* .padding */
13826 false, /* .isArray */
13827 false /* .isOptional */
13828},
13829{
13830 UA_TYPENAME("Results") /* .memberName */
13831 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13832 offsetof(UA_DeleteMonitoredItemsResponse, resultsSize) - offsetof(UA_DeleteMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13833 true, /* .isArray */
13834 false /* .isOptional */
13835},
13836{
13837 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13838 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13839 offsetof(UA_DeleteMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_DeleteMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
13840 true, /* .isArray */
13841 false /* .isOptional */
13842},};
13843
13844/* CreateSubscriptionRequest */
13845static UA_DataTypeMember CreateSubscriptionRequest_members[7] = {
13846{
13847 UA_TYPENAME("RequestHeader") /* .memberName */
13848 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13849 0, /* .padding */
13850 false, /* .isArray */
13851 false /* .isOptional */
13852},
13853{
13854 UA_TYPENAME("RequestedPublishingInterval") /* .memberName */
13855 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13856 offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - offsetof(UA_CreateSubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13857 false, /* .isArray */
13858 false /* .isOptional */
13859},
13860{
13861 UA_TYPENAME("RequestedLifetimeCount") /* .memberName */
13862 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13863 offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */
13864 false, /* .isArray */
13865 false /* .isOptional */
13866},
13867{
13868 UA_TYPENAME("RequestedMaxKeepAliveCount") /* .memberName */
13869 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13870 offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
13871 false, /* .isArray */
13872 false /* .isOptional */
13873},
13874{
13875 UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */
13876 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13877 offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
13878 false, /* .isArray */
13879 false /* .isOptional */
13880},
13881{
13882 UA_TYPENAME("PublishingEnabled") /* .memberName */
13883 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13884 offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
13885 false, /* .isArray */
13886 false /* .isOptional */
13887},
13888{
13889 UA_TYPENAME("Priority") /* .memberName */
13890 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
13891 offsetof(UA_CreateSubscriptionRequest, priority) - offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
13892 false, /* .isArray */
13893 false /* .isOptional */
13894},};
13895
13896/* CreateSubscriptionResponse */
13897static UA_DataTypeMember CreateSubscriptionResponse_members[5] = {
13898{
13899 UA_TYPENAME("ResponseHeader") /* .memberName */
13900 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13901 0, /* .padding */
13902 false, /* .isArray */
13903 false /* .isOptional */
13904},
13905{
13906 UA_TYPENAME("SubscriptionId") /* .memberName */
13907 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13908 offsetof(UA_CreateSubscriptionResponse, subscriptionId) - offsetof(UA_CreateSubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13909 false, /* .isArray */
13910 false /* .isOptional */
13911},
13912{
13913 UA_TYPENAME("RevisedPublishingInterval") /* .memberName */
13914 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13915 offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - offsetof(UA_CreateSubscriptionResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13916 false, /* .isArray */
13917 false /* .isOptional */
13918},
13919{
13920 UA_TYPENAME("RevisedLifetimeCount") /* .memberName */
13921 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13922 offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */
13923 false, /* .isArray */
13924 false /* .isOptional */
13925},
13926{
13927 UA_TYPENAME("RevisedMaxKeepAliveCount") /* .memberName */
13928 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13929 offsetof(UA_CreateSubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
13930 false, /* .isArray */
13931 false /* .isOptional */
13932},};
13933
13934/* ModifySubscriptionRequest */
13935static UA_DataTypeMember ModifySubscriptionRequest_members[7] = {
13936{
13937 UA_TYPENAME("RequestHeader") /* .memberName */
13938 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13939 0, /* .padding */
13940 false, /* .isArray */
13941 false /* .isOptional */
13942},
13943{
13944 UA_TYPENAME("SubscriptionId") /* .memberName */
13945 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13946 offsetof(UA_ModifySubscriptionRequest, subscriptionId) - offsetof(UA_ModifySubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13947 false, /* .isArray */
13948 false /* .isOptional */
13949},
13950{
13951 UA_TYPENAME("RequestedPublishingInterval") /* .memberName */
13952 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13953 offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - offsetof(UA_ModifySubscriptionRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13954 false, /* .isArray */
13955 false /* .isOptional */
13956},
13957{
13958 UA_TYPENAME("RequestedLifetimeCount") /* .memberName */
13959 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13960 offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */
13961 false, /* .isArray */
13962 false /* .isOptional */
13963},
13964{
13965 UA_TYPENAME("RequestedMaxKeepAliveCount") /* .memberName */
13966 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13967 offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
13968 false, /* .isArray */
13969 false /* .isOptional */
13970},
13971{
13972 UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */
13973 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13974 offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
13975 false, /* .isArray */
13976 false /* .isOptional */
13977},
13978{
13979 UA_TYPENAME("Priority") /* .memberName */
13980 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
13981 offsetof(UA_ModifySubscriptionRequest, priority) - offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
13982 false, /* .isArray */
13983 false /* .isOptional */
13984},};
13985
13986/* ModifySubscriptionResponse */
13987static UA_DataTypeMember ModifySubscriptionResponse_members[4] = {
13988{
13989 UA_TYPENAME("ResponseHeader") /* .memberName */
13990 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13991 0, /* .padding */
13992 false, /* .isArray */
13993 false /* .isOptional */
13994},
13995{
13996 UA_TYPENAME("RevisedPublishingInterval") /* .memberName */
13997 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13998 offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - offsetof(UA_ModifySubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13999 false, /* .isArray */
14000 false /* .isOptional */
14001},
14002{
14003 UA_TYPENAME("RevisedLifetimeCount") /* .memberName */
14004 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14005 offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */
14006 false, /* .isArray */
14007 false /* .isOptional */
14008},
14009{
14010 UA_TYPENAME("RevisedMaxKeepAliveCount") /* .memberName */
14011 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14012 offsetof(UA_ModifySubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
14013 false, /* .isArray */
14014 false /* .isOptional */
14015},};
14016
14017/* SetPublishingModeRequest */
14018static UA_DataTypeMember SetPublishingModeRequest_members[3] = {
14019{
14020 UA_TYPENAME("RequestHeader") /* .memberName */
14021 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14022 0, /* .padding */
14023 false, /* .isArray */
14024 false /* .isOptional */
14025},
14026{
14027 UA_TYPENAME("PublishingEnabled") /* .memberName */
14028 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
14029 offsetof(UA_SetPublishingModeRequest, publishingEnabled) - offsetof(UA_SetPublishingModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14030 false, /* .isArray */
14031 false /* .isOptional */
14032},
14033{
14034 UA_TYPENAME("SubscriptionIds") /* .memberName */
14035 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14036 offsetof(UA_SetPublishingModeRequest, subscriptionIdsSize) - offsetof(UA_SetPublishingModeRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
14037 true, /* .isArray */
14038 false /* .isOptional */
14039},};
14040
14041/* SetPublishingModeResponse */
14042static UA_DataTypeMember SetPublishingModeResponse_members[3] = {
14043{
14044 UA_TYPENAME("ResponseHeader") /* .memberName */
14045 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14046 0, /* .padding */
14047 false, /* .isArray */
14048 false /* .isOptional */
14049},
14050{
14051 UA_TYPENAME("Results") /* .memberName */
14052 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14053 offsetof(UA_SetPublishingModeResponse, resultsSize) - offsetof(UA_SetPublishingModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14054 true, /* .isArray */
14055 false /* .isOptional */
14056},
14057{
14058 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14059 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14060 offsetof(UA_SetPublishingModeResponse, diagnosticInfosSize) - offsetof(UA_SetPublishingModeResponse, results) - sizeof(void *), /* .padding */
14061 true, /* .isArray */
14062 false /* .isOptional */
14063},};
14064
14065/* NotificationMessage */
14066static UA_DataTypeMember NotificationMessage_members[3] = {
14067{
14068 UA_TYPENAME("SequenceNumber") /* .memberName */
14069 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14070 0, /* .padding */
14071 false, /* .isArray */
14072 false /* .isOptional */
14073},
14074{
14075 UA_TYPENAME("PublishTime") /* .memberName */
14076 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14077 offsetof(UA_NotificationMessage, publishTime) - offsetof(UA_NotificationMessage, sequenceNumber) - sizeof(UA_UInt32), /* .padding */
14078 false, /* .isArray */
14079 false /* .isOptional */
14080},
14081{
14082 UA_TYPENAME("NotificationData") /* .memberName */
14083 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
14084 offsetof(UA_NotificationMessage, notificationDataSize) - offsetof(UA_NotificationMessage, publishTime) - sizeof(UA_DateTime), /* .padding */
14085 true, /* .isArray */
14086 false /* .isOptional */
14087},};
14088
14089/* MonitoredItemNotification */
14090static UA_DataTypeMember MonitoredItemNotification_members[2] = {
14091{
14092 UA_TYPENAME("ClientHandle") /* .memberName */
14093 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14094 0, /* .padding */
14095 false, /* .isArray */
14096 false /* .isOptional */
14097},
14098{
14099 UA_TYPENAME("Value") /* .memberName */
14100 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
14101 offsetof(UA_MonitoredItemNotification, value) - offsetof(UA_MonitoredItemNotification, clientHandle) - sizeof(UA_UInt32), /* .padding */
14102 false, /* .isArray */
14103 false /* .isOptional */
14104},};
14105
14106/* EventFieldList */
14107static UA_DataTypeMember EventFieldList_members[2] = {
14108{
14109 UA_TYPENAME("ClientHandle") /* .memberName */
14110 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14111 0, /* .padding */
14112 false, /* .isArray */
14113 false /* .isOptional */
14114},
14115{
14116 UA_TYPENAME("EventFields") /* .memberName */
14117 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
14118 offsetof(UA_EventFieldList, eventFieldsSize) - offsetof(UA_EventFieldList, clientHandle) - sizeof(UA_UInt32), /* .padding */
14119 true, /* .isArray */
14120 false /* .isOptional */
14121},};
14122
14123/* HistoryEventFieldList */
14124static UA_DataTypeMember HistoryEventFieldList_members[1] = {
14125{
14126 UA_TYPENAME("EventFields") /* .memberName */
14127 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
14128 0, /* .padding */
14129 true, /* .isArray */
14130 false /* .isOptional */
14131},};
14132
14133/* StatusChangeNotification */
14134static UA_DataTypeMember StatusChangeNotification_members[2] = {
14135{
14136 UA_TYPENAME("Status") /* .memberName */
14137 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14138 0, /* .padding */
14139 false, /* .isArray */
14140 false /* .isOptional */
14141},
14142{
14143 UA_TYPENAME("DiagnosticInfo") /* .memberName */
14144 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14145 offsetof(UA_StatusChangeNotification, diagnosticInfo) - offsetof(UA_StatusChangeNotification, status) - sizeof(UA_StatusCode), /* .padding */
14146 false, /* .isArray */
14147 false /* .isOptional */
14148},};
14149
14150/* SubscriptionAcknowledgement */
14151static UA_DataTypeMember SubscriptionAcknowledgement_members[2] = {
14152{
14153 UA_TYPENAME("SubscriptionId") /* .memberName */
14154 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14155 0, /* .padding */
14156 false, /* .isArray */
14157 false /* .isOptional */
14158},
14159{
14160 UA_TYPENAME("SequenceNumber") /* .memberName */
14161 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14162 offsetof(UA_SubscriptionAcknowledgement, sequenceNumber) - offsetof(UA_SubscriptionAcknowledgement, subscriptionId) - sizeof(UA_UInt32), /* .padding */
14163 false, /* .isArray */
14164 false /* .isOptional */
14165},};
14166
14167/* PublishRequest */
14168static UA_DataTypeMember PublishRequest_members[2] = {
14169{
14170 UA_TYPENAME("RequestHeader") /* .memberName */
14171 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14172 0, /* .padding */
14173 false, /* .isArray */
14174 false /* .isOptional */
14175},
14176{
14177 UA_TYPENAME("SubscriptionAcknowledgements") /* .memberName */
14178 &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT], /* .memberType */
14179 offsetof(UA_PublishRequest, subscriptionAcknowledgementsSize) - offsetof(UA_PublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14180 true, /* .isArray */
14181 false /* .isOptional */
14182},};
14183
14184/* PublishResponse */
14185static UA_DataTypeMember PublishResponse_members[7] = {
14186{
14187 UA_TYPENAME("ResponseHeader") /* .memberName */
14188 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14189 0, /* .padding */
14190 false, /* .isArray */
14191 false /* .isOptional */
14192},
14193{
14194 UA_TYPENAME("SubscriptionId") /* .memberName */
14195 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14196 offsetof(UA_PublishResponse, subscriptionId) - offsetof(UA_PublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14197 false, /* .isArray */
14198 false /* .isOptional */
14199},
14200{
14201 UA_TYPENAME("AvailableSequenceNumbers") /* .memberName */
14202 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14203 offsetof(UA_PublishResponse, availableSequenceNumbersSize) - offsetof(UA_PublishResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */
14204 true, /* .isArray */
14205 false /* .isOptional */
14206},
14207{
14208 UA_TYPENAME("MoreNotifications") /* .memberName */
14209 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
14210 offsetof(UA_PublishResponse, moreNotifications) - offsetof(UA_PublishResponse, availableSequenceNumbers) - sizeof(void *), /* .padding */
14211 false, /* .isArray */
14212 false /* .isOptional */
14213},
14214{
14215 UA_TYPENAME("NotificationMessage") /* .memberName */
14216 &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], /* .memberType */
14217 offsetof(UA_PublishResponse, notificationMessage) - offsetof(UA_PublishResponse, moreNotifications) - sizeof(UA_Boolean), /* .padding */
14218 false, /* .isArray */
14219 false /* .isOptional */
14220},
14221{
14222 UA_TYPENAME("Results") /* .memberName */
14223 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14224 offsetof(UA_PublishResponse, resultsSize) - offsetof(UA_PublishResponse, notificationMessage) - sizeof(UA_NotificationMessage), /* .padding */
14225 true, /* .isArray */
14226 false /* .isOptional */
14227},
14228{
14229 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14230 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14231 offsetof(UA_PublishResponse, diagnosticInfosSize) - offsetof(UA_PublishResponse, results) - sizeof(void *), /* .padding */
14232 true, /* .isArray */
14233 false /* .isOptional */
14234},};
14235
14236/* RepublishRequest */
14237static UA_DataTypeMember RepublishRequest_members[3] = {
14238{
14239 UA_TYPENAME("RequestHeader") /* .memberName */
14240 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14241 0, /* .padding */
14242 false, /* .isArray */
14243 false /* .isOptional */
14244},
14245{
14246 UA_TYPENAME("SubscriptionId") /* .memberName */
14247 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14248 offsetof(UA_RepublishRequest, subscriptionId) - offsetof(UA_RepublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14249 false, /* .isArray */
14250 false /* .isOptional */
14251},
14252{
14253 UA_TYPENAME("RetransmitSequenceNumber") /* .memberName */
14254 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14255 offsetof(UA_RepublishRequest, retransmitSequenceNumber) - offsetof(UA_RepublishRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
14256 false, /* .isArray */
14257 false /* .isOptional */
14258},};
14259
14260/* RepublishResponse */
14261static UA_DataTypeMember RepublishResponse_members[2] = {
14262{
14263 UA_TYPENAME("ResponseHeader") /* .memberName */
14264 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14265 0, /* .padding */
14266 false, /* .isArray */
14267 false /* .isOptional */
14268},
14269{
14270 UA_TYPENAME("NotificationMessage") /* .memberName */
14271 &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], /* .memberType */
14272 offsetof(UA_RepublishResponse, notificationMessage) - offsetof(UA_RepublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14273 false, /* .isArray */
14274 false /* .isOptional */
14275},};
14276
14277/* TransferResult */
14278static UA_DataTypeMember TransferResult_members[2] = {
14279{
14280 UA_TYPENAME("StatusCode") /* .memberName */
14281 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14282 0, /* .padding */
14283 false, /* .isArray */
14284 false /* .isOptional */
14285},
14286{
14287 UA_TYPENAME("AvailableSequenceNumbers") /* .memberName */
14288 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14289 offsetof(UA_TransferResult, availableSequenceNumbersSize) - offsetof(UA_TransferResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
14290 true, /* .isArray */
14291 false /* .isOptional */
14292},};
14293
14294/* TransferSubscriptionsRequest */
14295static UA_DataTypeMember TransferSubscriptionsRequest_members[3] = {
14296{
14297 UA_TYPENAME("RequestHeader") /* .memberName */
14298 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14299 0, /* .padding */
14300 false, /* .isArray */
14301 false /* .isOptional */
14302},
14303{
14304 UA_TYPENAME("SubscriptionIds") /* .memberName */
14305 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14306 offsetof(UA_TransferSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_TransferSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14307 true, /* .isArray */
14308 false /* .isOptional */
14309},
14310{
14311 UA_TYPENAME("SendInitialValues") /* .memberName */
14312 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
14313 offsetof(UA_TransferSubscriptionsRequest, sendInitialValues) - offsetof(UA_TransferSubscriptionsRequest, subscriptionIds) - sizeof(void *), /* .padding */
14314 false, /* .isArray */
14315 false /* .isOptional */
14316},};
14317
14318/* TransferSubscriptionsResponse */
14319static UA_DataTypeMember TransferSubscriptionsResponse_members[3] = {
14320{
14321 UA_TYPENAME("ResponseHeader") /* .memberName */
14322 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14323 0, /* .padding */
14324 false, /* .isArray */
14325 false /* .isOptional */
14326},
14327{
14328 UA_TYPENAME("Results") /* .memberName */
14329 &UA_TYPES[UA_TYPES_TRANSFERRESULT], /* .memberType */
14330 offsetof(UA_TransferSubscriptionsResponse, resultsSize) - offsetof(UA_TransferSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14331 true, /* .isArray */
14332 false /* .isOptional */
14333},
14334{
14335 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14336 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14337 offsetof(UA_TransferSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_TransferSubscriptionsResponse, results) - sizeof(void *), /* .padding */
14338 true, /* .isArray */
14339 false /* .isOptional */
14340},};
14341
14342/* DeleteSubscriptionsRequest */
14343static UA_DataTypeMember DeleteSubscriptionsRequest_members[2] = {
14344{
14345 UA_TYPENAME("RequestHeader") /* .memberName */
14346 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14347 0, /* .padding */
14348 false, /* .isArray */
14349 false /* .isOptional */
14350},
14351{
14352 UA_TYPENAME("SubscriptionIds") /* .memberName */
14353 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14354 offsetof(UA_DeleteSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_DeleteSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14355 true, /* .isArray */
14356 false /* .isOptional */
14357},};
14358
14359/* DeleteSubscriptionsResponse */
14360static UA_DataTypeMember DeleteSubscriptionsResponse_members[3] = {
14361{
14362 UA_TYPENAME("ResponseHeader") /* .memberName */
14363 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14364 0, /* .padding */
14365 false, /* .isArray */
14366 false /* .isOptional */
14367},
14368{
14369 UA_TYPENAME("Results") /* .memberName */
14370 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14371 offsetof(UA_DeleteSubscriptionsResponse, resultsSize) - offsetof(UA_DeleteSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14372 true, /* .isArray */
14373 false /* .isOptional */
14374},
14375{
14376 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14377 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14378 offsetof(UA_DeleteSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_DeleteSubscriptionsResponse, results) - sizeof(void *), /* .padding */
14379 true, /* .isArray */
14380 false /* .isOptional */
14381},};
14382
14383/* BuildInfo */
14384static UA_DataTypeMember BuildInfo_members[6] = {
14385{
14386 UA_TYPENAME("ProductUri") /* .memberName */
14387 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14388 0, /* .padding */
14389 false, /* .isArray */
14390 false /* .isOptional */
14391},
14392{
14393 UA_TYPENAME("ManufacturerName") /* .memberName */
14394 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14395 offsetof(UA_BuildInfo, manufacturerName) - offsetof(UA_BuildInfo, productUri) - sizeof(UA_String), /* .padding */
14396 false, /* .isArray */
14397 false /* .isOptional */
14398},
14399{
14400 UA_TYPENAME("ProductName") /* .memberName */
14401 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14402 offsetof(UA_BuildInfo, productName) - offsetof(UA_BuildInfo, manufacturerName) - sizeof(UA_String), /* .padding */
14403 false, /* .isArray */
14404 false /* .isOptional */
14405},
14406{
14407 UA_TYPENAME("SoftwareVersion") /* .memberName */
14408 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14409 offsetof(UA_BuildInfo, softwareVersion) - offsetof(UA_BuildInfo, productName) - sizeof(UA_String), /* .padding */
14410 false, /* .isArray */
14411 false /* .isOptional */
14412},
14413{
14414 UA_TYPENAME("BuildNumber") /* .memberName */
14415 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14416 offsetof(UA_BuildInfo, buildNumber) - offsetof(UA_BuildInfo, softwareVersion) - sizeof(UA_String), /* .padding */
14417 false, /* .isArray */
14418 false /* .isOptional */
14419},
14420{
14421 UA_TYPENAME("BuildDate") /* .memberName */
14422 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14423 offsetof(UA_BuildInfo, buildDate) - offsetof(UA_BuildInfo, buildNumber) - sizeof(UA_String), /* .padding */
14424 false, /* .isArray */
14425 false /* .isOptional */
14426},};
14427
14428/* RedundancySupport */
14429#define RedundancySupport_members NULL
14430
14431/* ServerState */
14432#define ServerState_members NULL
14433
14434/* ServerDiagnosticsSummaryDataType */
14435static UA_DataTypeMember ServerDiagnosticsSummaryDataType_members[12] = {
14436{
14437 UA_TYPENAME("ServerViewCount") /* .memberName */
14438 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14439 0, /* .padding */
14440 false, /* .isArray */
14441 false /* .isOptional */
14442},
14443{
14444 UA_TYPENAME("CurrentSessionCount") /* .memberName */
14445 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14446 offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, serverViewCount) - sizeof(UA_UInt32), /* .padding */
14447 false, /* .isArray */
14448 false /* .isOptional */
14449},
14450{
14451 UA_TYPENAME("CumulatedSessionCount") /* .memberName */
14452 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14453 offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - sizeof(UA_UInt32), /* .padding */
14454 false, /* .isArray */
14455 false /* .isOptional */
14456},
14457{
14458 UA_TYPENAME("SecurityRejectedSessionCount") /* .memberName */
14459 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14460 offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - sizeof(UA_UInt32), /* .padding */
14461 false, /* .isArray */
14462 false /* .isOptional */
14463},
14464{
14465 UA_TYPENAME("RejectedSessionCount") /* .memberName */
14466 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14467 offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - sizeof(UA_UInt32), /* .padding */
14468 false, /* .isArray */
14469 false /* .isOptional */
14470},
14471{
14472 UA_TYPENAME("SessionTimeoutCount") /* .memberName */
14473 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14474 offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - sizeof(UA_UInt32), /* .padding */
14475 false, /* .isArray */
14476 false /* .isOptional */
14477},
14478{
14479 UA_TYPENAME("SessionAbortCount") /* .memberName */
14480 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14481 offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - sizeof(UA_UInt32), /* .padding */
14482 false, /* .isArray */
14483 false /* .isOptional */
14484},
14485{
14486 UA_TYPENAME("CurrentSubscriptionCount") /* .memberName */
14487 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14488 offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - sizeof(UA_UInt32), /* .padding */
14489 false, /* .isArray */
14490 false /* .isOptional */
14491},
14492{
14493 UA_TYPENAME("CumulatedSubscriptionCount") /* .memberName */
14494 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14495 offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - sizeof(UA_UInt32), /* .padding */
14496 false, /* .isArray */
14497 false /* .isOptional */
14498},
14499{
14500 UA_TYPENAME("PublishingIntervalCount") /* .memberName */
14501 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14502 offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - sizeof(UA_UInt32), /* .padding */
14503 false, /* .isArray */
14504 false /* .isOptional */
14505},
14506{
14507 UA_TYPENAME("SecurityRejectedRequestsCount") /* .memberName */
14508 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14509 offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - sizeof(UA_UInt32), /* .padding */
14510 false, /* .isArray */
14511 false /* .isOptional */
14512},
14513{
14514 UA_TYPENAME("RejectedRequestsCount") /* .memberName */
14515 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14516 offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - sizeof(UA_UInt32), /* .padding */
14517 false, /* .isArray */
14518 false /* .isOptional */
14519},};
14520
14521/* ServerStatusDataType */
14522static UA_DataTypeMember ServerStatusDataType_members[6] = {
14523{
14524 UA_TYPENAME("StartTime") /* .memberName */
14525 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14526 0, /* .padding */
14527 false, /* .isArray */
14528 false /* .isOptional */
14529},
14530{
14531 UA_TYPENAME("CurrentTime") /* .memberName */
14532 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14533 offsetof(UA_ServerStatusDataType, currentTime) - offsetof(UA_ServerStatusDataType, startTime) - sizeof(UA_DateTime), /* .padding */
14534 false, /* .isArray */
14535 false /* .isOptional */
14536},
14537{
14538 UA_TYPENAME("State") /* .memberName */
14539 &UA_TYPES[UA_TYPES_SERVERSTATE], /* .memberType */
14540 offsetof(UA_ServerStatusDataType, state) - offsetof(UA_ServerStatusDataType, currentTime) - sizeof(UA_DateTime), /* .padding */
14541 false, /* .isArray */
14542 false /* .isOptional */
14543},
14544{
14545 UA_TYPENAME("BuildInfo") /* .memberName */
14546 &UA_TYPES[UA_TYPES_BUILDINFO], /* .memberType */
14547 offsetof(UA_ServerStatusDataType, buildInfo) - offsetof(UA_ServerStatusDataType, state) - sizeof(UA_ServerState), /* .padding */
14548 false, /* .isArray */
14549 false /* .isOptional */
14550},
14551{
14552 UA_TYPENAME("SecondsTillShutdown") /* .memberName */
14553 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14554 offsetof(UA_ServerStatusDataType, secondsTillShutdown) - offsetof(UA_ServerStatusDataType, buildInfo) - sizeof(UA_BuildInfo), /* .padding */
14555 false, /* .isArray */
14556 false /* .isOptional */
14557},
14558{
14559 UA_TYPENAME("ShutdownReason") /* .memberName */
14560 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
14561 offsetof(UA_ServerStatusDataType, shutdownReason) - offsetof(UA_ServerStatusDataType, secondsTillShutdown) - sizeof(UA_UInt32), /* .padding */
14562 false, /* .isArray */
14563 false /* .isOptional */
14564},};
14565
14566/* Range */
14567static UA_DataTypeMember Range_members[2] = {
14568{
14569 UA_TYPENAME("Low") /* .memberName */
14570 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14571 0, /* .padding */
14572 false, /* .isArray */
14573 false /* .isOptional */
14574},
14575{
14576 UA_TYPENAME("High") /* .memberName */
14577 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14578 offsetof(UA_Range, high) - offsetof(UA_Range, low) - sizeof(UA_Double), /* .padding */
14579 false, /* .isArray */
14580 false /* .isOptional */
14581},};
14582
14583/* EUInformation */
14584static UA_DataTypeMember EUInformation_members[4] = {
14585{
14586 UA_TYPENAME("NamespaceUri") /* .memberName */
14587 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14588 0, /* .padding */
14589 false, /* .isArray */
14590 false /* .isOptional */
14591},
14592{
14593 UA_TYPENAME("UnitId") /* .memberName */
14594 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
14595 offsetof(UA_EUInformation, unitId) - offsetof(UA_EUInformation, namespaceUri) - sizeof(UA_String), /* .padding */
14596 false, /* .isArray */
14597 false /* .isOptional */
14598},
14599{
14600 UA_TYPENAME("DisplayName") /* .memberName */
14601 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
14602 offsetof(UA_EUInformation, displayName) - offsetof(UA_EUInformation, unitId) - sizeof(UA_Int32), /* .padding */
14603 false, /* .isArray */
14604 false /* .isOptional */
14605},
14606{
14607 UA_TYPENAME("Description") /* .memberName */
14608 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
14609 offsetof(UA_EUInformation, description) - offsetof(UA_EUInformation, displayName) - sizeof(UA_LocalizedText), /* .padding */
14610 false, /* .isArray */
14611 false /* .isOptional */
14612},};
14613
14614/* AxisScaleEnumeration */
14615#define AxisScaleEnumeration_members NULL
14616
14617/* ComplexNumberType */
14618static UA_DataTypeMember ComplexNumberType_members[2] = {
14619{
14620 UA_TYPENAME("Real") /* .memberName */
14621 &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
14622 0, /* .padding */
14623 false, /* .isArray */
14624 false /* .isOptional */
14625},
14626{
14627 UA_TYPENAME("Imaginary") /* .memberName */
14628 &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
14629 offsetof(UA_ComplexNumberType, imaginary) - offsetof(UA_ComplexNumberType, real) - sizeof(UA_Float), /* .padding */
14630 false, /* .isArray */
14631 false /* .isOptional */
14632},};
14633
14634/* DoubleComplexNumberType */
14635static UA_DataTypeMember DoubleComplexNumberType_members[2] = {
14636{
14637 UA_TYPENAME("Real") /* .memberName */
14638 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14639 0, /* .padding */
14640 false, /* .isArray */
14641 false /* .isOptional */
14642},
14643{
14644 UA_TYPENAME("Imaginary") /* .memberName */
14645 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14646 offsetof(UA_DoubleComplexNumberType, imaginary) - offsetof(UA_DoubleComplexNumberType, real) - sizeof(UA_Double), /* .padding */
14647 false, /* .isArray */
14648 false /* .isOptional */
14649},};
14650
14651/* AxisInformation */
14652static UA_DataTypeMember AxisInformation_members[5] = {
14653{
14654 UA_TYPENAME("EngineeringUnits") /* .memberName */
14655 &UA_TYPES[UA_TYPES_EUINFORMATION], /* .memberType */
14656 0, /* .padding */
14657 false, /* .isArray */
14658 false /* .isOptional */
14659},
14660{
14661 UA_TYPENAME("EURange") /* .memberName */
14662 &UA_TYPES[UA_TYPES_RANGE], /* .memberType */
14663 offsetof(UA_AxisInformation, eURange) - offsetof(UA_AxisInformation, engineeringUnits) - sizeof(UA_EUInformation), /* .padding */
14664 false, /* .isArray */
14665 false /* .isOptional */
14666},
14667{
14668 UA_TYPENAME("Title") /* .memberName */
14669 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
14670 offsetof(UA_AxisInformation, title) - offsetof(UA_AxisInformation, eURange) - sizeof(UA_Range), /* .padding */
14671 false, /* .isArray */
14672 false /* .isOptional */
14673},
14674{
14675 UA_TYPENAME("AxisScaleType") /* .memberName */
14676 &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION], /* .memberType */
14677 offsetof(UA_AxisInformation, axisScaleType) - offsetof(UA_AxisInformation, title) - sizeof(UA_LocalizedText), /* .padding */
14678 false, /* .isArray */
14679 false /* .isOptional */
14680},
14681{
14682 UA_TYPENAME("AxisSteps") /* .memberName */
14683 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14684 offsetof(UA_AxisInformation, axisStepsSize) - offsetof(UA_AxisInformation, axisScaleType) - sizeof(UA_AxisScaleEnumeration), /* .padding */
14685 true, /* .isArray */
14686 false /* .isOptional */
14687},};
14688
14689/* XVType */
14690static UA_DataTypeMember XVType_members[2] = {
14691{
14692 UA_TYPENAME("X") /* .memberName */
14693 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14694 0, /* .padding */
14695 false, /* .isArray */
14696 false /* .isOptional */
14697},
14698{
14699 UA_TYPENAME("Value") /* .memberName */
14700 &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
14701 offsetof(UA_XVType, value) - offsetof(UA_XVType, x) - sizeof(UA_Double), /* .padding */
14702 false, /* .isArray */
14703 false /* .isOptional */
14704},};
14705
14706/* EnumDefinition */
14707static UA_DataTypeMember EnumDefinition_members[1] = {
14708{
14709 UA_TYPENAME("Fields") /* .memberName */
14710 &UA_TYPES[UA_TYPES_ENUMFIELD], /* .memberType */
14711 0, /* .padding */
14712 true, /* .isArray */
14713 false /* .isOptional */
14714},};
14715
14716/* ReadEventDetails */
14717static UA_DataTypeMember ReadEventDetails_members[4] = {
14718{
14719 UA_TYPENAME("NumValuesPerNode") /* .memberName */
14720 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14721 0, /* .padding */
14722 false, /* .isArray */
14723 false /* .isOptional */
14724},
14725{
14726 UA_TYPENAME("StartTime") /* .memberName */
14727 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14728 offsetof(UA_ReadEventDetails, startTime) - offsetof(UA_ReadEventDetails, numValuesPerNode) - sizeof(UA_UInt32), /* .padding */
14729 false, /* .isArray */
14730 false /* .isOptional */
14731},
14732{
14733 UA_TYPENAME("EndTime") /* .memberName */
14734 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14735 offsetof(UA_ReadEventDetails, endTime) - offsetof(UA_ReadEventDetails, startTime) - sizeof(UA_DateTime), /* .padding */
14736 false, /* .isArray */
14737 false /* .isOptional */
14738},
14739{
14740 UA_TYPENAME("Filter") /* .memberName */
14741 &UA_TYPES[UA_TYPES_EVENTFILTER], /* .memberType */
14742 offsetof(UA_ReadEventDetails, filter) - offsetof(UA_ReadEventDetails, endTime) - sizeof(UA_DateTime), /* .padding */
14743 false, /* .isArray */
14744 false /* .isOptional */
14745},};
14746
14747/* ReadProcessedDetails */
14748static UA_DataTypeMember ReadProcessedDetails_members[5] = {
14749{
14750 UA_TYPENAME("StartTime") /* .memberName */
14751 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14752 0, /* .padding */
14753 false, /* .isArray */
14754 false /* .isOptional */
14755},
14756{
14757 UA_TYPENAME("EndTime") /* .memberName */
14758 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14759 offsetof(UA_ReadProcessedDetails, endTime) - offsetof(UA_ReadProcessedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
14760 false, /* .isArray */
14761 false /* .isOptional */
14762},
14763{
14764 UA_TYPENAME("ProcessingInterval") /* .memberName */
14765 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14766 offsetof(UA_ReadProcessedDetails, processingInterval) - offsetof(UA_ReadProcessedDetails, endTime) - sizeof(UA_DateTime), /* .padding */
14767 false, /* .isArray */
14768 false /* .isOptional */
14769},
14770{
14771 UA_TYPENAME("AggregateType") /* .memberName */
14772 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
14773 offsetof(UA_ReadProcessedDetails, aggregateTypeSize) - offsetof(UA_ReadProcessedDetails, processingInterval) - sizeof(UA_Double), /* .padding */
14774 true, /* .isArray */
14775 false /* .isOptional */
14776},
14777{
14778 UA_TYPENAME("AggregateConfiguration") /* .memberName */
14779 &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */
14780 offsetof(UA_ReadProcessedDetails, aggregateConfiguration) - offsetof(UA_ReadProcessedDetails, aggregateType) - sizeof(void *), /* .padding */
14781 false, /* .isArray */
14782 false /* .isOptional */
14783},};
14784
14785/* ModificationInfo */
14786static UA_DataTypeMember ModificationInfo_members[3] = {
14787{
14788 UA_TYPENAME("ModificationTime") /* .memberName */
14789 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14790 0, /* .padding */
14791 false, /* .isArray */
14792 false /* .isOptional */
14793},
14794{
14795 UA_TYPENAME("UpdateType") /* .memberName */
14796 &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE], /* .memberType */
14797 offsetof(UA_ModificationInfo, updateType) - offsetof(UA_ModificationInfo, modificationTime) - sizeof(UA_DateTime), /* .padding */
14798 false, /* .isArray */
14799 false /* .isOptional */
14800},
14801{
14802 UA_TYPENAME("UserName") /* .memberName */
14803 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14804 offsetof(UA_ModificationInfo, userName) - offsetof(UA_ModificationInfo, updateType) - sizeof(UA_HistoryUpdateType), /* .padding */
14805 false, /* .isArray */
14806 false /* .isOptional */
14807},};
14808
14809/* HistoryModifiedData */
14810static UA_DataTypeMember HistoryModifiedData_members[2] = {
14811{
14812 UA_TYPENAME("DataValues") /* .memberName */
14813 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
14814 0, /* .padding */
14815 true, /* .isArray */
14816 false /* .isOptional */
14817},
14818{
14819 UA_TYPENAME("ModificationInfos") /* .memberName */
14820 &UA_TYPES[UA_TYPES_MODIFICATIONINFO], /* .memberType */
14821 offsetof(UA_HistoryModifiedData, modificationInfosSize) - offsetof(UA_HistoryModifiedData, dataValues) - sizeof(void *), /* .padding */
14822 true, /* .isArray */
14823 false /* .isOptional */
14824},};
14825
14826/* HistoryEvent */
14827static UA_DataTypeMember HistoryEvent_members[1] = {
14828{
14829 UA_TYPENAME("Events") /* .memberName */
14830 &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST], /* .memberType */
14831 0, /* .padding */
14832 true, /* .isArray */
14833 false /* .isOptional */
14834},};
14835
14836/* DataChangeNotification */
14837static UA_DataTypeMember DataChangeNotification_members[2] = {
14838{
14839 UA_TYPENAME("MonitoredItems") /* .memberName */
14840 &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION], /* .memberType */
14841 0, /* .padding */
14842 true, /* .isArray */
14843 false /* .isOptional */
14844},
14845{
14846 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14847 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14848 offsetof(UA_DataChangeNotification, diagnosticInfosSize) - offsetof(UA_DataChangeNotification, monitoredItems) - sizeof(void *), /* .padding */
14849 true, /* .isArray */
14850 false /* .isOptional */
14851},};
14852
14853/* EventNotificationList */
14854static UA_DataTypeMember EventNotificationList_members[1] = {
14855{
14856 UA_TYPENAME("Events") /* .memberName */
14857 &UA_TYPES[UA_TYPES_EVENTFIELDLIST], /* .memberType */
14858 0, /* .padding */
14859 true, /* .isArray */
14860 false /* .isOptional */
14861},};
14862const UA_DataType UA_TYPES[UA_TYPES_COUNT] = {
14863/* Boolean */
14864{
14865 UA_TYPENAME("Boolean") /* .typeName */
14866 {0, UA_NODEIDTYPE_NUMERIC, {.numeric: 1LU}}, /* .typeId */
14867 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14868 sizeof(UA_Boolean), /* .memSize */
14869 UA_DATATYPEKIND_BOOLEAN, /* .typeKind */
14870 true, /* .pointerFree */
14871 false, /* .overlayable */
14872 0, /* .membersSize */
14873 Boolean_members /* .members */
14874},
14875/* SByte */
14876{
14877 UA_TYPENAME("SByte") /* .typeName */
14878 {0, UA_NODEIDTYPE_NUMERIC, {2LU}}, /* .typeId */
14879 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14880 sizeof(UA_SByte), /* .memSize */
14881 UA_DATATYPEKIND_SBYTE, /* .typeKind */
14882 true, /* .pointerFree */
14883 true, /* .overlayable */
14884 0, /* .membersSize */
14885 SByte_members /* .members */
14886},
14887/* Byte */
14888{
14889 UA_TYPENAME("Byte") /* .typeName */
14890 {0, UA_NODEIDTYPE_NUMERIC, {3LU}}, /* .typeId */
14891 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14892 sizeof(UA_Byte), /* .memSize */
14893 UA_DATATYPEKIND_BYTE, /* .typeKind */
14894 true, /* .pointerFree */
14895 true, /* .overlayable */
14896 0, /* .membersSize */
14897 Byte_members /* .members */
14898},
14899/* Int16 */
14900{
14901 UA_TYPENAME("Int16") /* .typeName */
14902 {0, UA_NODEIDTYPE_NUMERIC, {4LU}}, /* .typeId */
14903 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14904 sizeof(UA_Int16), /* .memSize */
14905 UA_DATATYPEKIND_INT16, /* .typeKind */
14906 true, /* .pointerFree */
14907 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14908 0, /* .membersSize */
14909 Int16_members /* .members */
14910},
14911/* UInt16 */
14912{
14913 UA_TYPENAME("UInt16") /* .typeName */
14914 {0, UA_NODEIDTYPE_NUMERIC, {5LU}}, /* .typeId */
14915 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14916 sizeof(UA_UInt16), /* .memSize */
14917 UA_DATATYPEKIND_UINT16, /* .typeKind */
14918 true, /* .pointerFree */
14919 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14920 0, /* .membersSize */
14921 UInt16_members /* .members */
14922},
14923/* Int32 */
14924{
14925 UA_TYPENAME("Int32") /* .typeName */
14926 {0, UA_NODEIDTYPE_NUMERIC, {6LU}}, /* .typeId */
14927 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14928 sizeof(UA_Int32), /* .memSize */
14929 UA_DATATYPEKIND_INT32, /* .typeKind */
14930 true, /* .pointerFree */
14931 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14932 0, /* .membersSize */
14933 Int32_members /* .members */
14934},
14935/* UInt32 */
14936{
14937 UA_TYPENAME("UInt32") /* .typeName */
14938 {0, UA_NODEIDTYPE_NUMERIC, {7LU}}, /* .typeId */
14939 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14940 sizeof(UA_UInt32), /* .memSize */
14941 UA_DATATYPEKIND_UINT32, /* .typeKind */
14942 true, /* .pointerFree */
14943 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14944 0, /* .membersSize */
14945 UInt32_members /* .members */
14946},
14947/* Int64 */
14948{
14949 UA_TYPENAME("Int64") /* .typeName */
14950 {0, UA_NODEIDTYPE_NUMERIC, {8LU}}, /* .typeId */
14951 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14952 sizeof(UA_Int64), /* .memSize */
14953 UA_DATATYPEKIND_INT64, /* .typeKind */
14954 true, /* .pointerFree */
14955 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14956 0, /* .membersSize */
14957 Int64_members /* .members */
14958},
14959/* UInt64 */
14960{
14961 UA_TYPENAME("UInt64") /* .typeName */
14962 {0, UA_NODEIDTYPE_NUMERIC, {9LU}}, /* .typeId */
14963 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14964 sizeof(UA_UInt64), /* .memSize */
14965 UA_DATATYPEKIND_UINT64, /* .typeKind */
14966 true, /* .pointerFree */
14967 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14968 0, /* .membersSize */
14969 UInt64_members /* .members */
14970},
14971/* Float */
14972{
14973 UA_TYPENAME("Float") /* .typeName */
14974 {0, UA_NODEIDTYPE_NUMERIC, {10LU}}, /* .typeId */
14975 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14976 sizeof(UA_Float), /* .memSize */
14977 UA_DATATYPEKIND_FLOAT, /* .typeKind */
14978 true, /* .pointerFree */
14979 UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */
14980 0, /* .membersSize */
14981 Float_members /* .members */
14982},
14983/* Double */
14984{
14985 UA_TYPENAME("Double") /* .typeName */
14986 {0, UA_NODEIDTYPE_NUMERIC, {11LU}}, /* .typeId */
14987 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14988 sizeof(UA_Double), /* .memSize */
14989 UA_DATATYPEKIND_DOUBLE, /* .typeKind */
14990 true, /* .pointerFree */
14991 UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */
14992 0, /* .membersSize */
14993 Double_members /* .members */
14994},
14995/* String */
14996{
14997 UA_TYPENAME("String") /* .typeName */
14998 {0, UA_NODEIDTYPE_NUMERIC, {12LU}}, /* .typeId */
14999 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15000 sizeof(UA_String), /* .memSize */
15001 UA_DATATYPEKIND_STRING, /* .typeKind */
15002 false, /* .pointerFree */
15003 false, /* .overlayable */
15004 0, /* .membersSize */
15005 String_members /* .members */
15006},
15007/* DateTime */
15008{
15009 UA_TYPENAME("DateTime") /* .typeName */
15010 {0, UA_NODEIDTYPE_NUMERIC, {13LU}}, /* .typeId */
15011 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15012 sizeof(UA_DateTime), /* .memSize */
15013 UA_DATATYPEKIND_DATETIME, /* .typeKind */
15014 true, /* .pointerFree */
15015 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15016 0, /* .membersSize */
15017 DateTime_members /* .members */
15018},
15019/* Guid */
15020{
15021 UA_TYPENAME("Guid") /* .typeName */
15022 {0, UA_NODEIDTYPE_NUMERIC, {14LU}}, /* .typeId */
15023 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15024 sizeof(UA_Guid), /* .memSize */
15025 UA_DATATYPEKIND_GUID, /* .typeKind */
15026 true, /* .pointerFree */
15027 (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 */
15028 0, /* .membersSize */
15029 Guid_members /* .members */
15030},
15031/* ByteString */
15032{
15033 UA_TYPENAME("ByteString") /* .typeName */
15034 {0, UA_NODEIDTYPE_NUMERIC, {15LU}}, /* .typeId */
15035 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15036 sizeof(UA_ByteString), /* .memSize */
15037 UA_DATATYPEKIND_BYTESTRING, /* .typeKind */
15038 false, /* .pointerFree */
15039 false, /* .overlayable */
15040 0, /* .membersSize */
15041 ByteString_members /* .members */
15042},
15043/* XmlElement */
15044{
15045 UA_TYPENAME("XmlElement") /* .typeName */
15046 {0, UA_NODEIDTYPE_NUMERIC, {16LU}}, /* .typeId */
15047 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15048 sizeof(UA_XmlElement), /* .memSize */
15049 UA_DATATYPEKIND_XMLELEMENT, /* .typeKind */
15050 false, /* .pointerFree */
15051 false, /* .overlayable */
15052 0, /* .membersSize */
15053 XmlElement_members /* .members */
15054},
15055/* NodeId */
15056{
15057 UA_TYPENAME("NodeId") /* .typeName */
15058 {0, UA_NODEIDTYPE_NUMERIC, {17LU}}, /* .typeId */
15059 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15060 sizeof(UA_NodeId), /* .memSize */
15061 UA_DATATYPEKIND_NODEID, /* .typeKind */
15062 false, /* .pointerFree */
15063 false, /* .overlayable */
15064 0, /* .membersSize */
15065 NodeId_members /* .members */
15066},
15067/* ExpandedNodeId */
15068{
15069 UA_TYPENAME("ExpandedNodeId") /* .typeName */
15070 {0, UA_NODEIDTYPE_NUMERIC, {18LU}}, /* .typeId */
15071 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15072 sizeof(UA_ExpandedNodeId), /* .memSize */
15073 UA_DATATYPEKIND_EXPANDEDNODEID, /* .typeKind */
15074 false, /* .pointerFree */
15075 false, /* .overlayable */
15076 0, /* .membersSize */
15077 ExpandedNodeId_members /* .members */
15078},
15079/* StatusCode */
15080{
15081 UA_TYPENAME("StatusCode") /* .typeName */
15082 {0, UA_NODEIDTYPE_NUMERIC, {19LU}}, /* .typeId */
15083 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15084 sizeof(UA_StatusCode), /* .memSize */
15085 UA_DATATYPEKIND_STATUSCODE, /* .typeKind */
15086 true, /* .pointerFree */
15087 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15088 0, /* .membersSize */
15089 StatusCode_members /* .members */
15090},
15091/* QualifiedName */
15092{
15093 UA_TYPENAME("QualifiedName") /* .typeName */
15094 {0, UA_NODEIDTYPE_NUMERIC, {20LU}}, /* .typeId */
15095 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15096 sizeof(UA_QualifiedName), /* .memSize */
15097 UA_DATATYPEKIND_QUALIFIEDNAME, /* .typeKind */
15098 false, /* .pointerFree */
15099 false, /* .overlayable */
15100 0, /* .membersSize */
15101 QualifiedName_members /* .members */
15102},
15103/* LocalizedText */
15104{
15105 UA_TYPENAME("LocalizedText") /* .typeName */
15106 {0, UA_NODEIDTYPE_NUMERIC, {21LU}}, /* .typeId */
15107 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15108 sizeof(UA_LocalizedText), /* .memSize */
15109 UA_DATATYPEKIND_LOCALIZEDTEXT, /* .typeKind */
15110 false, /* .pointerFree */
15111 false, /* .overlayable */
15112 0, /* .membersSize */
15113 LocalizedText_members /* .members */
15114},
15115/* ExtensionObject */
15116{
15117 UA_TYPENAME("ExtensionObject") /* .typeName */
15118 {0, UA_NODEIDTYPE_NUMERIC, {22LU}}, /* .typeId */
15119 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15120 sizeof(UA_ExtensionObject), /* .memSize */
15121 UA_DATATYPEKIND_EXTENSIONOBJECT, /* .typeKind */
15122 false, /* .pointerFree */
15123 false, /* .overlayable */
15124 0, /* .membersSize */
15125 ExtensionObject_members /* .members */
15126},
15127/* DataValue */
15128{
15129 UA_TYPENAME("DataValue") /* .typeName */
15130 {0, UA_NODEIDTYPE_NUMERIC, {23LU}}, /* .typeId */
15131 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15132 sizeof(UA_DataValue), /* .memSize */
15133 UA_DATATYPEKIND_DATAVALUE, /* .typeKind */
15134 false, /* .pointerFree */
15135 false, /* .overlayable */
15136 0, /* .membersSize */
15137 DataValue_members /* .members */
15138},
15139/* Variant */
15140{
15141 UA_TYPENAME("Variant") /* .typeName */
15142 {0, UA_NODEIDTYPE_NUMERIC, {24LU}}, /* .typeId */
15143 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15144 sizeof(UA_Variant), /* .memSize */
15145 UA_DATATYPEKIND_VARIANT, /* .typeKind */
15146 false, /* .pointerFree */
15147 false, /* .overlayable */
15148 0, /* .membersSize */
15149 Variant_members /* .members */
15150},
15151/* DiagnosticInfo */
15152{
15153 UA_TYPENAME("DiagnosticInfo") /* .typeName */
15154 {0, UA_NODEIDTYPE_NUMERIC, {25LU}}, /* .typeId */
15155 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15156 sizeof(UA_DiagnosticInfo), /* .memSize */
15157 UA_DATATYPEKIND_DIAGNOSTICINFO, /* .typeKind */
15158 false, /* .pointerFree */
15159 false, /* .overlayable */
15160 0, /* .membersSize */
15161 DiagnosticInfo_members /* .members */
15162},
15163/* KeyValuePair */
15164{
15165 UA_TYPENAME("KeyValuePair") /* .typeName */
15166 {0, UA_NODEIDTYPE_NUMERIC, {14533LU}}, /* .typeId */
15167 {0, UA_NODEIDTYPE_NUMERIC, {14846LU}}, /* .binaryEncodingId */
15168 sizeof(UA_KeyValuePair), /* .memSize */
15169 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15170 false, /* .pointerFree */
15171 false, /* .overlayable */
15172 2, /* .membersSize */
15173 KeyValuePair_members /* .members */
15174},
15175/* NodeClass */
15176{
15177 UA_TYPENAME("NodeClass") /* .typeName */
15178 {0, UA_NODEIDTYPE_NUMERIC, {257LU}}, /* .typeId */
15179 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15180 sizeof(UA_NodeClass), /* .memSize */
15181 UA_DATATYPEKIND_ENUM, /* .typeKind */
15182 true, /* .pointerFree */
15183 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15184 0, /* .membersSize */
15185 NodeClass_members /* .members */
15186},
15187/* StructureType */
15188{
15189 UA_TYPENAME("StructureType") /* .typeName */
15190 {0, UA_NODEIDTYPE_NUMERIC, {98LU}}, /* .typeId */
15191 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15192 sizeof(UA_StructureType), /* .memSize */
15193 UA_DATATYPEKIND_ENUM, /* .typeKind */
15194 true, /* .pointerFree */
15195 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15196 0, /* .membersSize */
15197 StructureType_members /* .members */
15198},
15199/* StructureField */
15200{
15201 UA_TYPENAME("StructureField") /* .typeName */
15202 {0, UA_NODEIDTYPE_NUMERIC, {101LU}}, /* .typeId */
15203 {0, UA_NODEIDTYPE_NUMERIC, {14844LU}}, /* .binaryEncodingId */
15204 sizeof(UA_StructureField), /* .memSize */
15205 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15206 false, /* .pointerFree */
15207 false, /* .overlayable */
15208 7, /* .membersSize */
15209 StructureField_members /* .members */
15210},
15211/* StructureDefinition */
15212{
15213 UA_TYPENAME("StructureDefinition") /* .typeName */
15214 {0, UA_NODEIDTYPE_NUMERIC, {99LU}}, /* .typeId */
15215 {0, UA_NODEIDTYPE_NUMERIC, {122LU}}, /* .binaryEncodingId */
15216 sizeof(UA_StructureDefinition), /* .memSize */
15217 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15218 false, /* .pointerFree */
15219 false, /* .overlayable */
15220 4, /* .membersSize */
15221 StructureDefinition_members /* .members */
15222},
15223/* Argument */
15224{
15225 UA_TYPENAME("Argument") /* .typeName */
15226 {0, UA_NODEIDTYPE_NUMERIC, {296LU}}, /* .typeId */
15227 {0, UA_NODEIDTYPE_NUMERIC, {298LU}}, /* .binaryEncodingId */
15228 sizeof(UA_Argument), /* .memSize */
15229 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15230 false, /* .pointerFree */
15231 false, /* .overlayable */
15232 5, /* .membersSize */
15233 Argument_members /* .members */
15234},
15235/* EnumValueType */
15236{
15237 UA_TYPENAME("EnumValueType") /* .typeName */
15238 {0, UA_NODEIDTYPE_NUMERIC, {7594LU}}, /* .typeId */
15239 {0, UA_NODEIDTYPE_NUMERIC, {8251LU}}, /* .binaryEncodingId */
15240 sizeof(UA_EnumValueType), /* .memSize */
15241 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15242 false, /* .pointerFree */
15243 false, /* .overlayable */
15244 3, /* .membersSize */
15245 EnumValueType_members /* .members */
15246},
15247/* EnumField */
15248{
15249 UA_TYPENAME("EnumField") /* .typeName */
15250 {0, UA_NODEIDTYPE_NUMERIC, {102LU}}, /* .typeId */
15251 {0, UA_NODEIDTYPE_NUMERIC, {14845LU}}, /* .binaryEncodingId */
15252 sizeof(UA_EnumField), /* .memSize */
15253 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15254 false, /* .pointerFree */
15255 false, /* .overlayable */
15256 4, /* .membersSize */
15257 EnumField_members /* .members */
15258},
15259/* Duration */
15260{
15261 UA_TYPENAME("Duration") /* .typeName */
15262 {0, UA_NODEIDTYPE_NUMERIC, {290LU}}, /* .typeId */
15263 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15264 sizeof(UA_Duration), /* .memSize */
15265 UA_DATATYPEKIND_DOUBLE, /* .typeKind */
15266 false, /* .pointerFree */
15267 false, /* .overlayable */
15268 0, /* .membersSize */
15269 Duration_members /* .members */
15270},
15271/* UtcTime */
15272{
15273 UA_TYPENAME("UtcTime") /* .typeName */
15274 {0, UA_NODEIDTYPE_NUMERIC, {294LU}}, /* .typeId */
15275 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15276 sizeof(UA_UtcTime), /* .memSize */
15277 UA_DATATYPEKIND_DATETIME, /* .typeKind */
15278 false, /* .pointerFree */
15279 false, /* .overlayable */
15280 0, /* .membersSize */
15281 UtcTime_members /* .members */
15282},
15283/* LocaleId */
15284{
15285 UA_TYPENAME("LocaleId") /* .typeName */
15286 {0, UA_NODEIDTYPE_NUMERIC, {295LU}}, /* .typeId */
15287 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15288 sizeof(UA_LocaleId), /* .memSize */
15289 UA_DATATYPEKIND_STRING, /* .typeKind */
15290 false, /* .pointerFree */
15291 false, /* .overlayable */
15292 0, /* .membersSize */
15293 LocaleId_members /* .members */
15294},
15295/* TimeZoneDataType */
15296{
15297 UA_TYPENAME("TimeZoneDataType") /* .typeName */
15298 {0, UA_NODEIDTYPE_NUMERIC, {8912LU}}, /* .typeId */
15299 {0, UA_NODEIDTYPE_NUMERIC, {8917LU}}, /* .binaryEncodingId */
15300 sizeof(UA_TimeZoneDataType), /* .memSize */
15301 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15302 true, /* .pointerFree */
15303 false, /* .overlayable */
15304 2, /* .membersSize */
15305 TimeZoneDataType_members /* .members */
15306},
15307/* ApplicationType */
15308{
15309 UA_TYPENAME("ApplicationType") /* .typeName */
15310 {0, UA_NODEIDTYPE_NUMERIC, {307LU}}, /* .typeId */
15311 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15312 sizeof(UA_ApplicationType), /* .memSize */
15313 UA_DATATYPEKIND_ENUM, /* .typeKind */
15314 true, /* .pointerFree */
15315 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15316 0, /* .membersSize */
15317 ApplicationType_members /* .members */
15318},
15319/* ApplicationDescription */
15320{
15321 UA_TYPENAME("ApplicationDescription") /* .typeName */
15322 {0, UA_NODEIDTYPE_NUMERIC, {308LU}}, /* .typeId */
15323 {0, UA_NODEIDTYPE_NUMERIC, {310LU}}, /* .binaryEncodingId */
15324 sizeof(UA_ApplicationDescription), /* .memSize */
15325 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15326 false, /* .pointerFree */
15327 false, /* .overlayable */
15328 7, /* .membersSize */
15329 ApplicationDescription_members /* .members */
15330},
15331/* RequestHeader */
15332{
15333 UA_TYPENAME("RequestHeader") /* .typeName */
15334 {0, UA_NODEIDTYPE_NUMERIC, {389LU}}, /* .typeId */
15335 {0, UA_NODEIDTYPE_NUMERIC, {391LU}}, /* .binaryEncodingId */
15336 sizeof(UA_RequestHeader), /* .memSize */
15337 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15338 false, /* .pointerFree */
15339 false, /* .overlayable */
15340 7, /* .membersSize */
15341 RequestHeader_members /* .members */
15342},
15343/* ResponseHeader */
15344{
15345 UA_TYPENAME("ResponseHeader") /* .typeName */
15346 {0, UA_NODEIDTYPE_NUMERIC, {392LU}}, /* .typeId */
15347 {0, UA_NODEIDTYPE_NUMERIC, {394LU}}, /* .binaryEncodingId */
15348 sizeof(UA_ResponseHeader), /* .memSize */
15349 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15350 false, /* .pointerFree */
15351 false, /* .overlayable */
15352 6, /* .membersSize */
15353 ResponseHeader_members /* .members */
15354},
15355/* ServiceFault */
15356{
15357 UA_TYPENAME("ServiceFault") /* .typeName */
15358 {0, UA_NODEIDTYPE_NUMERIC, {395LU}}, /* .typeId */
15359 {0, UA_NODEIDTYPE_NUMERIC, {397LU}}, /* .binaryEncodingId */
15360 sizeof(UA_ServiceFault), /* .memSize */
15361 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15362 false, /* .pointerFree */
15363 false, /* .overlayable */
15364 1, /* .membersSize */
15365 ServiceFault_members /* .members */
15366},
15367/* FindServersRequest */
15368{
15369 UA_TYPENAME("FindServersRequest") /* .typeName */
15370 {0, UA_NODEIDTYPE_NUMERIC, {420LU}}, /* .typeId */
15371 {0, UA_NODEIDTYPE_NUMERIC, {422LU}}, /* .binaryEncodingId */
15372 sizeof(UA_FindServersRequest), /* .memSize */
15373 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15374 false, /* .pointerFree */
15375 false, /* .overlayable */
15376 4, /* .membersSize */
15377 FindServersRequest_members /* .members */
15378},
15379/* FindServersResponse */
15380{
15381 UA_TYPENAME("FindServersResponse") /* .typeName */
15382 {0, UA_NODEIDTYPE_NUMERIC, {423LU}}, /* .typeId */
15383 {0, UA_NODEIDTYPE_NUMERIC, {425LU}}, /* .binaryEncodingId */
15384 sizeof(UA_FindServersResponse), /* .memSize */
15385 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15386 false, /* .pointerFree */
15387 false, /* .overlayable */
15388 2, /* .membersSize */
15389 FindServersResponse_members /* .members */
15390},
15391/* MessageSecurityMode */
15392{
15393 UA_TYPENAME("MessageSecurityMode") /* .typeName */
15394 {0, UA_NODEIDTYPE_NUMERIC, {302LU}}, /* .typeId */
15395 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15396 sizeof(UA_MessageSecurityMode), /* .memSize */
15397 UA_DATATYPEKIND_ENUM, /* .typeKind */
15398 true, /* .pointerFree */
15399 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15400 0, /* .membersSize */
15401 MessageSecurityMode_members /* .members */
15402},
15403/* UserTokenType */
15404{
15405 UA_TYPENAME("UserTokenType") /* .typeName */
15406 {0, UA_NODEIDTYPE_NUMERIC, {303LU}}, /* .typeId */
15407 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15408 sizeof(UA_UserTokenType), /* .memSize */
15409 UA_DATATYPEKIND_ENUM, /* .typeKind */
15410 true, /* .pointerFree */
15411 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15412 0, /* .membersSize */
15413 UserTokenType_members /* .members */
15414},
15415/* UserTokenPolicy */
15416{
15417 UA_TYPENAME("UserTokenPolicy") /* .typeName */
15418 {0, UA_NODEIDTYPE_NUMERIC, {304LU}}, /* .typeId */
15419 {0, UA_NODEIDTYPE_NUMERIC, {306LU}}, /* .binaryEncodingId */
15420 sizeof(UA_UserTokenPolicy), /* .memSize */
15421 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15422 false, /* .pointerFree */
15423 false, /* .overlayable */
15424 5, /* .membersSize */
15425 UserTokenPolicy_members /* .members */
15426},
15427/* EndpointDescription */
15428{
15429 UA_TYPENAME("EndpointDescription") /* .typeName */
15430 {0, UA_NODEIDTYPE_NUMERIC, {312LU}}, /* .typeId */
15431 {0, UA_NODEIDTYPE_NUMERIC, {314LU}}, /* .binaryEncodingId */
15432 sizeof(UA_EndpointDescription), /* .memSize */
15433 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15434 false, /* .pointerFree */
15435 false, /* .overlayable */
15436 8, /* .membersSize */
15437 EndpointDescription_members /* .members */
15438},
15439/* GetEndpointsRequest */
15440{
15441 UA_TYPENAME("GetEndpointsRequest") /* .typeName */
15442 {0, UA_NODEIDTYPE_NUMERIC, {426LU}}, /* .typeId */
15443 {0, UA_NODEIDTYPE_NUMERIC, {428LU}}, /* .binaryEncodingId */
15444 sizeof(UA_GetEndpointsRequest), /* .memSize */
15445 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15446 false, /* .pointerFree */
15447 false, /* .overlayable */
15448 4, /* .membersSize */
15449 GetEndpointsRequest_members /* .members */
15450},
15451/* GetEndpointsResponse */
15452{
15453 UA_TYPENAME("GetEndpointsResponse") /* .typeName */
15454 {0, UA_NODEIDTYPE_NUMERIC, {429LU}}, /* .typeId */
15455 {0, UA_NODEIDTYPE_NUMERIC, {431LU}}, /* .binaryEncodingId */
15456 sizeof(UA_GetEndpointsResponse), /* .memSize */
15457 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15458 false, /* .pointerFree */
15459 false, /* .overlayable */
15460 2, /* .membersSize */
15461 GetEndpointsResponse_members /* .members */
15462},
15463/* SecurityTokenRequestType */
15464{
15465 UA_TYPENAME("SecurityTokenRequestType") /* .typeName */
15466 {0, UA_NODEIDTYPE_NUMERIC, {315LU}}, /* .typeId */
15467 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15468 sizeof(UA_SecurityTokenRequestType), /* .memSize */
15469 UA_DATATYPEKIND_ENUM, /* .typeKind */
15470 true, /* .pointerFree */
15471 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15472 0, /* .membersSize */
15473 SecurityTokenRequestType_members /* .members */
15474},
15475/* ChannelSecurityToken */
15476{
15477 UA_TYPENAME("ChannelSecurityToken") /* .typeName */
15478 {0, UA_NODEIDTYPE_NUMERIC, {441LU}}, /* .typeId */
15479 {0, UA_NODEIDTYPE_NUMERIC, {443LU}}, /* .binaryEncodingId */
15480 sizeof(UA_ChannelSecurityToken), /* .memSize */
15481 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15482 true, /* .pointerFree */
15483 false, /* .overlayable */
15484 4, /* .membersSize */
15485 ChannelSecurityToken_members /* .members */
15486},
15487/* OpenSecureChannelRequest */
15488{
15489 UA_TYPENAME("OpenSecureChannelRequest") /* .typeName */
15490 {0, UA_NODEIDTYPE_NUMERIC, {444LU}}, /* .typeId */
15491 {0, UA_NODEIDTYPE_NUMERIC, {446LU}}, /* .binaryEncodingId */
15492 sizeof(UA_OpenSecureChannelRequest), /* .memSize */
15493 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15494 false, /* .pointerFree */
15495 false, /* .overlayable */
15496 6, /* .membersSize */
15497 OpenSecureChannelRequest_members /* .members */
15498},
15499/* OpenSecureChannelResponse */
15500{
15501 UA_TYPENAME("OpenSecureChannelResponse") /* .typeName */
15502 {0, UA_NODEIDTYPE_NUMERIC, {447LU}}, /* .typeId */
15503 {0, UA_NODEIDTYPE_NUMERIC, {449LU}}, /* .binaryEncodingId */
15504 sizeof(UA_OpenSecureChannelResponse), /* .memSize */
15505 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15506 false, /* .pointerFree */
15507 false, /* .overlayable */
15508 4, /* .membersSize */
15509 OpenSecureChannelResponse_members /* .members */
15510},
15511/* CloseSecureChannelRequest */
15512{
15513 UA_TYPENAME("CloseSecureChannelRequest") /* .typeName */
15514 {0, UA_NODEIDTYPE_NUMERIC, {450LU}}, /* .typeId */
15515 {0, UA_NODEIDTYPE_NUMERIC, {452LU}}, /* .binaryEncodingId */
15516 sizeof(UA_CloseSecureChannelRequest), /* .memSize */
15517 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15518 false, /* .pointerFree */
15519 false, /* .overlayable */
15520 1, /* .membersSize */
15521 CloseSecureChannelRequest_members /* .members */
15522},
15523/* CloseSecureChannelResponse */
15524{
15525 UA_TYPENAME("CloseSecureChannelResponse") /* .typeName */
15526 {0, UA_NODEIDTYPE_NUMERIC, {453LU}}, /* .typeId */
15527 {0, UA_NODEIDTYPE_NUMERIC, {455LU}}, /* .binaryEncodingId */
15528 sizeof(UA_CloseSecureChannelResponse), /* .memSize */
15529 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15530 false, /* .pointerFree */
15531 false, /* .overlayable */
15532 1, /* .membersSize */
15533 CloseSecureChannelResponse_members /* .members */
15534},
15535/* SignedSoftwareCertificate */
15536{
15537 UA_TYPENAME("SignedSoftwareCertificate") /* .typeName */
15538 {0, UA_NODEIDTYPE_NUMERIC, {344LU}}, /* .typeId */
15539 {0, UA_NODEIDTYPE_NUMERIC, {346LU}}, /* .binaryEncodingId */
15540 sizeof(UA_SignedSoftwareCertificate), /* .memSize */
15541 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15542 false, /* .pointerFree */
15543 false, /* .overlayable */
15544 2, /* .membersSize */
15545 SignedSoftwareCertificate_members /* .members */
15546},
15547/* SignatureData */
15548{
15549 UA_TYPENAME("SignatureData") /* .typeName */
15550 {0, UA_NODEIDTYPE_NUMERIC, {456LU}}, /* .typeId */
15551 {0, UA_NODEIDTYPE_NUMERIC, {458LU}}, /* .binaryEncodingId */
15552 sizeof(UA_SignatureData), /* .memSize */
15553 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15554 false, /* .pointerFree */
15555 false, /* .overlayable */
15556 2, /* .membersSize */
15557 SignatureData_members /* .members */
15558},
15559/* CreateSessionRequest */
15560{
15561 UA_TYPENAME("CreateSessionRequest") /* .typeName */
15562 {0, UA_NODEIDTYPE_NUMERIC, {459LU}}, /* .typeId */
15563 {0, UA_NODEIDTYPE_NUMERIC, {461LU}}, /* .binaryEncodingId */
15564 sizeof(UA_CreateSessionRequest), /* .memSize */
15565 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15566 false, /* .pointerFree */
15567 false, /* .overlayable */
15568 9, /* .membersSize */
15569 CreateSessionRequest_members /* .members */
15570},
15571/* CreateSessionResponse */
15572{
15573 UA_TYPENAME("CreateSessionResponse") /* .typeName */
15574 {0, UA_NODEIDTYPE_NUMERIC, {462LU}}, /* .typeId */
15575 {0, UA_NODEIDTYPE_NUMERIC, {464LU}}, /* .binaryEncodingId */
15576 sizeof(UA_CreateSessionResponse), /* .memSize */
15577 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15578 false, /* .pointerFree */
15579 false, /* .overlayable */
15580 10, /* .membersSize */
15581 CreateSessionResponse_members /* .members */
15582},
15583/* UserIdentityToken */
15584{
15585 UA_TYPENAME("UserIdentityToken") /* .typeName */
15586 {0, UA_NODEIDTYPE_NUMERIC, {316LU}}, /* .typeId */
15587 {0, UA_NODEIDTYPE_NUMERIC, {318LU}}, /* .binaryEncodingId */
15588 sizeof(UA_UserIdentityToken), /* .memSize */
15589 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15590 false, /* .pointerFree */
15591 false, /* .overlayable */
15592 1, /* .membersSize */
15593 UserIdentityToken_members /* .members */
15594},
15595/* AnonymousIdentityToken */
15596{
15597 UA_TYPENAME("AnonymousIdentityToken") /* .typeName */
15598 {0, UA_NODEIDTYPE_NUMERIC, {319LU}}, /* .typeId */
15599 {0, UA_NODEIDTYPE_NUMERIC, {321LU}}, /* .binaryEncodingId */
15600 sizeof(UA_AnonymousIdentityToken), /* .memSize */
15601 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15602 false, /* .pointerFree */
15603 false, /* .overlayable */
15604 1, /* .membersSize */
15605 AnonymousIdentityToken_members /* .members */
15606},
15607/* UserNameIdentityToken */
15608{
15609 UA_TYPENAME("UserNameIdentityToken") /* .typeName */
15610 {0, UA_NODEIDTYPE_NUMERIC, {322LU}}, /* .typeId */
15611 {0, UA_NODEIDTYPE_NUMERIC, {324LU}}, /* .binaryEncodingId */
15612 sizeof(UA_UserNameIdentityToken), /* .memSize */
15613 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15614 false, /* .pointerFree */
15615 false, /* .overlayable */
15616 4, /* .membersSize */
15617 UserNameIdentityToken_members /* .members */
15618},
15619/* X509IdentityToken */
15620{
15621 UA_TYPENAME("X509IdentityToken") /* .typeName */
15622 {0, UA_NODEIDTYPE_NUMERIC, {325LU}}, /* .typeId */
15623 {0, UA_NODEIDTYPE_NUMERIC, {327LU}}, /* .binaryEncodingId */
15624 sizeof(UA_X509IdentityToken), /* .memSize */
15625 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15626 false, /* .pointerFree */
15627 false, /* .overlayable */
15628 2, /* .membersSize */
15629 X509IdentityToken_members /* .members */
15630},
15631/* IssuedIdentityToken */
15632{
15633 UA_TYPENAME("IssuedIdentityToken") /* .typeName */
15634 {0, UA_NODEIDTYPE_NUMERIC, {938LU}}, /* .typeId */
15635 {0, UA_NODEIDTYPE_NUMERIC, {940LU}}, /* .binaryEncodingId */
15636 sizeof(UA_IssuedIdentityToken), /* .memSize */
15637 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15638 false, /* .pointerFree */
15639 false, /* .overlayable */
15640 3, /* .membersSize */
15641 IssuedIdentityToken_members /* .members */
15642},
15643/* ActivateSessionRequest */
15644{
15645 UA_TYPENAME("ActivateSessionRequest") /* .typeName */
15646 {0, UA_NODEIDTYPE_NUMERIC, {465LU}}, /* .typeId */
15647 {0, UA_NODEIDTYPE_NUMERIC, {467LU}}, /* .binaryEncodingId */
15648 sizeof(UA_ActivateSessionRequest), /* .memSize */
15649 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15650 false, /* .pointerFree */
15651 false, /* .overlayable */
15652 6, /* .membersSize */
15653 ActivateSessionRequest_members /* .members */
15654},
15655/* ActivateSessionResponse */
15656{
15657 UA_TYPENAME("ActivateSessionResponse") /* .typeName */
15658 {0, UA_NODEIDTYPE_NUMERIC, {468LU}}, /* .typeId */
15659 {0, UA_NODEIDTYPE_NUMERIC, {470LU}}, /* .binaryEncodingId */
15660 sizeof(UA_ActivateSessionResponse), /* .memSize */
15661 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15662 false, /* .pointerFree */
15663 false, /* .overlayable */
15664 4, /* .membersSize */
15665 ActivateSessionResponse_members /* .members */
15666},
15667/* CloseSessionRequest */
15668{
15669 UA_TYPENAME("CloseSessionRequest") /* .typeName */
15670 {0, UA_NODEIDTYPE_NUMERIC, {471LU}}, /* .typeId */
15671 {0, UA_NODEIDTYPE_NUMERIC, {473LU}}, /* .binaryEncodingId */
15672 sizeof(UA_CloseSessionRequest), /* .memSize */
15673 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15674 false, /* .pointerFree */
15675 false, /* .overlayable */
15676 2, /* .membersSize */
15677 CloseSessionRequest_members /* .members */
15678},
15679/* CloseSessionResponse */
15680{
15681 UA_TYPENAME("CloseSessionResponse") /* .typeName */
15682 {0, UA_NODEIDTYPE_NUMERIC, {474LU}}, /* .typeId */
15683 {0, UA_NODEIDTYPE_NUMERIC, {476LU}}, /* .binaryEncodingId */
15684 sizeof(UA_CloseSessionResponse), /* .memSize */
15685 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15686 false, /* .pointerFree */
15687 false, /* .overlayable */
15688 1, /* .membersSize */
15689 CloseSessionResponse_members /* .members */
15690},
15691/* NodeAttributesMask */
15692{
15693 UA_TYPENAME("NodeAttributesMask") /* .typeName */
15694 {0, UA_NODEIDTYPE_NUMERIC, {348LU}}, /* .typeId */
15695 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15696 sizeof(UA_NodeAttributesMask), /* .memSize */
15697 UA_DATATYPEKIND_ENUM, /* .typeKind */
15698 true, /* .pointerFree */
15699 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15700 0, /* .membersSize */
15701 NodeAttributesMask_members /* .members */
15702},
15703/* NodeAttributes */
15704{
15705 UA_TYPENAME("NodeAttributes") /* .typeName */
15706 {0, UA_NODEIDTYPE_NUMERIC, {349LU}}, /* .typeId */
15707 {0, UA_NODEIDTYPE_NUMERIC, {351LU}}, /* .binaryEncodingId */
15708 sizeof(UA_NodeAttributes), /* .memSize */
15709 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15710 false, /* .pointerFree */
15711 false, /* .overlayable */
15712 5, /* .membersSize */
15713 NodeAttributes_members /* .members */
15714},
15715/* ObjectAttributes */
15716{
15717 UA_TYPENAME("ObjectAttributes") /* .typeName */
15718 {0, UA_NODEIDTYPE_NUMERIC, {352LU}}, /* .typeId */
15719 {0, UA_NODEIDTYPE_NUMERIC, {354LU}}, /* .binaryEncodingId */
15720 sizeof(UA_ObjectAttributes), /* .memSize */
15721 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15722 false, /* .pointerFree */
15723 false, /* .overlayable */
15724 6, /* .membersSize */
15725 ObjectAttributes_members /* .members */
15726},
15727/* VariableAttributes */
15728{
15729 UA_TYPENAME("VariableAttributes") /* .typeName */
15730 {0, UA_NODEIDTYPE_NUMERIC, {355LU}}, /* .typeId */
15731 {0, UA_NODEIDTYPE_NUMERIC, {357LU}}, /* .binaryEncodingId */
15732 sizeof(UA_VariableAttributes), /* .memSize */
15733 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15734 false, /* .pointerFree */
15735 false, /* .overlayable */
15736 13, /* .membersSize */
15737 VariableAttributes_members /* .members */
15738},
15739/* MethodAttributes */
15740{
15741 UA_TYPENAME("MethodAttributes") /* .typeName */
15742 {0, UA_NODEIDTYPE_NUMERIC, {358LU}}, /* .typeId */
15743 {0, UA_NODEIDTYPE_NUMERIC, {360LU}}, /* .binaryEncodingId */
15744 sizeof(UA_MethodAttributes), /* .memSize */
15745 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15746 false, /* .pointerFree */
15747 false, /* .overlayable */
15748 7, /* .membersSize */
15749 MethodAttributes_members /* .members */
15750},
15751/* ObjectTypeAttributes */
15752{
15753 UA_TYPENAME("ObjectTypeAttributes") /* .typeName */
15754 {0, UA_NODEIDTYPE_NUMERIC, {361LU}}, /* .typeId */
15755 {0, UA_NODEIDTYPE_NUMERIC, {363LU}}, /* .binaryEncodingId */
15756 sizeof(UA_ObjectTypeAttributes), /* .memSize */
15757 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15758 false, /* .pointerFree */
15759 false, /* .overlayable */
15760 6, /* .membersSize */
15761 ObjectTypeAttributes_members /* .members */
15762},
15763/* VariableTypeAttributes */
15764{
15765 UA_TYPENAME("VariableTypeAttributes") /* .typeName */
15766 {0, UA_NODEIDTYPE_NUMERIC, {364LU}}, /* .typeId */
15767 {0, UA_NODEIDTYPE_NUMERIC, {366LU}}, /* .binaryEncodingId */
15768 sizeof(UA_VariableTypeAttributes), /* .memSize */
15769 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15770 false, /* .pointerFree */
15771 false, /* .overlayable */
15772 10, /* .membersSize */
15773 VariableTypeAttributes_members /* .members */
15774},
15775/* ReferenceTypeAttributes */
15776{
15777 UA_TYPENAME("ReferenceTypeAttributes") /* .typeName */
15778 {0, UA_NODEIDTYPE_NUMERIC, {367LU}}, /* .typeId */
15779 {0, UA_NODEIDTYPE_NUMERIC, {369LU}}, /* .binaryEncodingId */
15780 sizeof(UA_ReferenceTypeAttributes), /* .memSize */
15781 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15782 false, /* .pointerFree */
15783 false, /* .overlayable */
15784 8, /* .membersSize */
15785 ReferenceTypeAttributes_members /* .members */
15786},
15787/* DataTypeAttributes */
15788{
15789 UA_TYPENAME("DataTypeAttributes") /* .typeName */
15790 {0, UA_NODEIDTYPE_NUMERIC, {370LU}}, /* .typeId */
15791 {0, UA_NODEIDTYPE_NUMERIC, {372LU}}, /* .binaryEncodingId */
15792 sizeof(UA_DataTypeAttributes), /* .memSize */
15793 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15794 false, /* .pointerFree */
15795 false, /* .overlayable */
15796 6, /* .membersSize */
15797 DataTypeAttributes_members /* .members */
15798},
15799/* ViewAttributes */
15800{
15801 UA_TYPENAME("ViewAttributes") /* .typeName */
15802 {0, UA_NODEIDTYPE_NUMERIC, {373LU}}, /* .typeId */
15803 {0, UA_NODEIDTYPE_NUMERIC, {375LU}}, /* .binaryEncodingId */
15804 sizeof(UA_ViewAttributes), /* .memSize */
15805 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15806 false, /* .pointerFree */
15807 false, /* .overlayable */
15808 7, /* .membersSize */
15809 ViewAttributes_members /* .members */
15810},
15811/* AddNodesItem */
15812{
15813 UA_TYPENAME("AddNodesItem") /* .typeName */
15814 {0, UA_NODEIDTYPE_NUMERIC, {376LU}}, /* .typeId */
15815 {0, UA_NODEIDTYPE_NUMERIC, {378LU}}, /* .binaryEncodingId */
15816 sizeof(UA_AddNodesItem), /* .memSize */
15817 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15818 false, /* .pointerFree */
15819 false, /* .overlayable */
15820 7, /* .membersSize */
15821 AddNodesItem_members /* .members */
15822},
15823/* AddNodesResult */
15824{
15825 UA_TYPENAME("AddNodesResult") /* .typeName */
15826 {0, UA_NODEIDTYPE_NUMERIC, {483LU}}, /* .typeId */
15827 {0, UA_NODEIDTYPE_NUMERIC, {485LU}}, /* .binaryEncodingId */
15828 sizeof(UA_AddNodesResult), /* .memSize */
15829 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15830 false, /* .pointerFree */
15831 false, /* .overlayable */
15832 2, /* .membersSize */
15833 AddNodesResult_members /* .members */
15834},
15835/* AddNodesRequest */
15836{
15837 UA_TYPENAME("AddNodesRequest") /* .typeName */
15838 {0, UA_NODEIDTYPE_NUMERIC, {486LU}}, /* .typeId */
15839 {0, UA_NODEIDTYPE_NUMERIC, {488LU}}, /* .binaryEncodingId */
15840 sizeof(UA_AddNodesRequest), /* .memSize */
15841 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15842 false, /* .pointerFree */
15843 false, /* .overlayable */
15844 2, /* .membersSize */
15845 AddNodesRequest_members /* .members */
15846},
15847/* AddNodesResponse */
15848{
15849 UA_TYPENAME("AddNodesResponse") /* .typeName */
15850 {0, UA_NODEIDTYPE_NUMERIC, {489LU}}, /* .typeId */
15851 {0, UA_NODEIDTYPE_NUMERIC, {491LU}}, /* .binaryEncodingId */
15852 sizeof(UA_AddNodesResponse), /* .memSize */
15853 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15854 false, /* .pointerFree */
15855 false, /* .overlayable */
15856 3, /* .membersSize */
15857 AddNodesResponse_members /* .members */
15858},
15859/* AddReferencesItem */
15860{
15861 UA_TYPENAME("AddReferencesItem") /* .typeName */
15862 {0, UA_NODEIDTYPE_NUMERIC, {379LU}}, /* .typeId */
15863 {0, UA_NODEIDTYPE_NUMERIC, {381LU}}, /* .binaryEncodingId */
15864 sizeof(UA_AddReferencesItem), /* .memSize */
15865 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15866 false, /* .pointerFree */
15867 false, /* .overlayable */
15868 6, /* .membersSize */
15869 AddReferencesItem_members /* .members */
15870},
15871/* AddReferencesRequest */
15872{
15873 UA_TYPENAME("AddReferencesRequest") /* .typeName */
15874 {0, UA_NODEIDTYPE_NUMERIC, {492LU}}, /* .typeId */
15875 {0, UA_NODEIDTYPE_NUMERIC, {494LU}}, /* .binaryEncodingId */
15876 sizeof(UA_AddReferencesRequest), /* .memSize */
15877 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15878 false, /* .pointerFree */
15879 false, /* .overlayable */
15880 2, /* .membersSize */
15881 AddReferencesRequest_members /* .members */
15882},
15883/* AddReferencesResponse */
15884{
15885 UA_TYPENAME("AddReferencesResponse") /* .typeName */
15886 {0, UA_NODEIDTYPE_NUMERIC, {495LU}}, /* .typeId */
15887 {0, UA_NODEIDTYPE_NUMERIC, {497LU}}, /* .binaryEncodingId */
15888 sizeof(UA_AddReferencesResponse), /* .memSize */
15889 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15890 false, /* .pointerFree */
15891 false, /* .overlayable */
15892 3, /* .membersSize */
15893 AddReferencesResponse_members /* .members */
15894},
15895/* DeleteNodesItem */
15896{
15897 UA_TYPENAME("DeleteNodesItem") /* .typeName */
15898 {0, UA_NODEIDTYPE_NUMERIC, {382LU}}, /* .typeId */
15899 {0, UA_NODEIDTYPE_NUMERIC, {384LU}}, /* .binaryEncodingId */
15900 sizeof(UA_DeleteNodesItem), /* .memSize */
15901 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15902 false, /* .pointerFree */
15903 false, /* .overlayable */
15904 2, /* .membersSize */
15905 DeleteNodesItem_members /* .members */
15906},
15907/* DeleteNodesRequest */
15908{
15909 UA_TYPENAME("DeleteNodesRequest") /* .typeName */
15910 {0, UA_NODEIDTYPE_NUMERIC, {498LU}}, /* .typeId */
15911 {0, UA_NODEIDTYPE_NUMERIC, {500LU}}, /* .binaryEncodingId */
15912 sizeof(UA_DeleteNodesRequest), /* .memSize */
15913 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15914 false, /* .pointerFree */
15915 false, /* .overlayable */
15916 2, /* .membersSize */
15917 DeleteNodesRequest_members /* .members */
15918},
15919/* DeleteNodesResponse */
15920{
15921 UA_TYPENAME("DeleteNodesResponse") /* .typeName */
15922 {0, UA_NODEIDTYPE_NUMERIC, {501LU}}, /* .typeId */
15923 {0, UA_NODEIDTYPE_NUMERIC, {503LU}}, /* .binaryEncodingId */
15924 sizeof(UA_DeleteNodesResponse), /* .memSize */
15925 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15926 false, /* .pointerFree */
15927 false, /* .overlayable */
15928 3, /* .membersSize */
15929 DeleteNodesResponse_members /* .members */
15930},
15931/* DeleteReferencesItem */
15932{
15933 UA_TYPENAME("DeleteReferencesItem") /* .typeName */
15934 {0, UA_NODEIDTYPE_NUMERIC, {385LU}}, /* .typeId */
15935 {0, UA_NODEIDTYPE_NUMERIC, {387LU}}, /* .binaryEncodingId */
15936 sizeof(UA_DeleteReferencesItem), /* .memSize */
15937 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15938 false, /* .pointerFree */
15939 false, /* .overlayable */
15940 5, /* .membersSize */
15941 DeleteReferencesItem_members /* .members */
15942},
15943/* DeleteReferencesRequest */
15944{
15945 UA_TYPENAME("DeleteReferencesRequest") /* .typeName */
15946 {0, UA_NODEIDTYPE_NUMERIC, {504LU}}, /* .typeId */
15947 {0, UA_NODEIDTYPE_NUMERIC, {506LU}}, /* .binaryEncodingId */
15948 sizeof(UA_DeleteReferencesRequest), /* .memSize */
15949 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15950 false, /* .pointerFree */
15951 false, /* .overlayable */
15952 2, /* .membersSize */
15953 DeleteReferencesRequest_members /* .members */
15954},
15955/* DeleteReferencesResponse */
15956{
15957 UA_TYPENAME("DeleteReferencesResponse") /* .typeName */
15958 {0, UA_NODEIDTYPE_NUMERIC, {507LU}}, /* .typeId */
15959 {0, UA_NODEIDTYPE_NUMERIC, {509LU}}, /* .binaryEncodingId */
15960 sizeof(UA_DeleteReferencesResponse), /* .memSize */
15961 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15962 false, /* .pointerFree */
15963 false, /* .overlayable */
15964 3, /* .membersSize */
15965 DeleteReferencesResponse_members /* .members */
15966},
15967/* BrowseDirection */
15968{
15969 UA_TYPENAME("BrowseDirection") /* .typeName */
15970 {0, UA_NODEIDTYPE_NUMERIC, {510LU}}, /* .typeId */
15971 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15972 sizeof(UA_BrowseDirection), /* .memSize */
15973 UA_DATATYPEKIND_ENUM, /* .typeKind */
15974 true, /* .pointerFree */
15975 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15976 0, /* .membersSize */
15977 BrowseDirection_members /* .members */
15978},
15979/* ViewDescription */
15980{
15981 UA_TYPENAME("ViewDescription") /* .typeName */
15982 {0, UA_NODEIDTYPE_NUMERIC, {511LU}}, /* .typeId */
15983 {0, UA_NODEIDTYPE_NUMERIC, {513LU}}, /* .binaryEncodingId */
15984 sizeof(UA_ViewDescription), /* .memSize */
15985 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15986 false, /* .pointerFree */
15987 false, /* .overlayable */
15988 3, /* .membersSize */
15989 ViewDescription_members /* .members */
15990},
15991/* BrowseDescription */
15992{
15993 UA_TYPENAME("BrowseDescription") /* .typeName */
15994 {0, UA_NODEIDTYPE_NUMERIC, {514LU}}, /* .typeId */
15995 {0, UA_NODEIDTYPE_NUMERIC, {516LU}}, /* .binaryEncodingId */
15996 sizeof(UA_BrowseDescription), /* .memSize */
15997 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15998 false, /* .pointerFree */
15999 false, /* .overlayable */
16000 6, /* .membersSize */
16001 BrowseDescription_members /* .members */
16002},
16003/* BrowseResultMask */
16004{
16005 UA_TYPENAME("BrowseResultMask") /* .typeName */
16006 {0, UA_NODEIDTYPE_NUMERIC, {517LU}}, /* .typeId */
16007 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16008 sizeof(UA_BrowseResultMask), /* .memSize */
16009 UA_DATATYPEKIND_ENUM, /* .typeKind */
16010 true, /* .pointerFree */
16011 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16012 0, /* .membersSize */
16013 BrowseResultMask_members /* .members */
16014},
16015/* ReferenceDescription */
16016{
16017 UA_TYPENAME("ReferenceDescription") /* .typeName */
16018 {0, UA_NODEIDTYPE_NUMERIC, {518LU}}, /* .typeId */
16019 {0, UA_NODEIDTYPE_NUMERIC, {520LU}}, /* .binaryEncodingId */
16020 sizeof(UA_ReferenceDescription), /* .memSize */
16021 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16022 false, /* .pointerFree */
16023 false, /* .overlayable */
16024 7, /* .membersSize */
16025 ReferenceDescription_members /* .members */
16026},
16027/* BrowseResult */
16028{
16029 UA_TYPENAME("BrowseResult") /* .typeName */
16030 {0, UA_NODEIDTYPE_NUMERIC, {522LU}}, /* .typeId */
16031 {0, UA_NODEIDTYPE_NUMERIC, {524LU}}, /* .binaryEncodingId */
16032 sizeof(UA_BrowseResult), /* .memSize */
16033 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16034 false, /* .pointerFree */
16035 false, /* .overlayable */
16036 3, /* .membersSize */
16037 BrowseResult_members /* .members */
16038},
16039/* BrowseRequest */
16040{
16041 UA_TYPENAME("BrowseRequest") /* .typeName */
16042 {0, UA_NODEIDTYPE_NUMERIC, {525LU}}, /* .typeId */
16043 {0, UA_NODEIDTYPE_NUMERIC, {527LU}}, /* .binaryEncodingId */
16044 sizeof(UA_BrowseRequest), /* .memSize */
16045 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16046 false, /* .pointerFree */
16047 false, /* .overlayable */
16048 4, /* .membersSize */
16049 BrowseRequest_members /* .members */
16050},
16051/* BrowseResponse */
16052{
16053 UA_TYPENAME("BrowseResponse") /* .typeName */
16054 {0, UA_NODEIDTYPE_NUMERIC, {528LU}}, /* .typeId */
16055 {0, UA_NODEIDTYPE_NUMERIC, {530LU}}, /* .binaryEncodingId */
16056 sizeof(UA_BrowseResponse), /* .memSize */
16057 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16058 false, /* .pointerFree */
16059 false, /* .overlayable */
16060 3, /* .membersSize */
16061 BrowseResponse_members /* .members */
16062},
16063/* BrowseNextRequest */
16064{
16065 UA_TYPENAME("BrowseNextRequest") /* .typeName */
16066 {0, UA_NODEIDTYPE_NUMERIC, {531LU}}, /* .typeId */
16067 {0, UA_NODEIDTYPE_NUMERIC, {533LU}}, /* .binaryEncodingId */
16068 sizeof(UA_BrowseNextRequest), /* .memSize */
16069 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16070 false, /* .pointerFree */
16071 false, /* .overlayable */
16072 3, /* .membersSize */
16073 BrowseNextRequest_members /* .members */
16074},
16075/* BrowseNextResponse */
16076{
16077 UA_TYPENAME("BrowseNextResponse") /* .typeName */
16078 {0, UA_NODEIDTYPE_NUMERIC, {534LU}}, /* .typeId */
16079 {0, UA_NODEIDTYPE_NUMERIC, {536LU}}, /* .binaryEncodingId */
16080 sizeof(UA_BrowseNextResponse), /* .memSize */
16081 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16082 false, /* .pointerFree */
16083 false, /* .overlayable */
16084 3, /* .membersSize */
16085 BrowseNextResponse_members /* .members */
16086},
16087/* RelativePathElement */
16088{
16089 UA_TYPENAME("RelativePathElement") /* .typeName */
16090 {0, UA_NODEIDTYPE_NUMERIC, {537LU}}, /* .typeId */
16091 {0, UA_NODEIDTYPE_NUMERIC, {539LU}}, /* .binaryEncodingId */
16092 sizeof(UA_RelativePathElement), /* .memSize */
16093 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16094 false, /* .pointerFree */
16095 false, /* .overlayable */
16096 4, /* .membersSize */
16097 RelativePathElement_members /* .members */
16098},
16099/* RelativePath */
16100{
16101 UA_TYPENAME("RelativePath") /* .typeName */
16102 {0, UA_NODEIDTYPE_NUMERIC, {540LU}}, /* .typeId */
16103 {0, UA_NODEIDTYPE_NUMERIC, {542LU}}, /* .binaryEncodingId */
16104 sizeof(UA_RelativePath), /* .memSize */
16105 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16106 false, /* .pointerFree */
16107 false, /* .overlayable */
16108 1, /* .membersSize */
16109 RelativePath_members /* .members */
16110},
16111/* BrowsePath */
16112{
16113 UA_TYPENAME("BrowsePath") /* .typeName */
16114 {0, UA_NODEIDTYPE_NUMERIC, {543LU}}, /* .typeId */
16115 {0, UA_NODEIDTYPE_NUMERIC, {545LU}}, /* .binaryEncodingId */
16116 sizeof(UA_BrowsePath), /* .memSize */
16117 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16118 false, /* .pointerFree */
16119 false, /* .overlayable */
16120 2, /* .membersSize */
16121 BrowsePath_members /* .members */
16122},
16123/* BrowsePathTarget */
16124{
16125 UA_TYPENAME("BrowsePathTarget") /* .typeName */
16126 {0, UA_NODEIDTYPE_NUMERIC, {546LU}}, /* .typeId */
16127 {0, UA_NODEIDTYPE_NUMERIC, {548LU}}, /* .binaryEncodingId */
16128 sizeof(UA_BrowsePathTarget), /* .memSize */
16129 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16130 false, /* .pointerFree */
16131 false, /* .overlayable */
16132 2, /* .membersSize */
16133 BrowsePathTarget_members /* .members */
16134},
16135/* BrowsePathResult */
16136{
16137 UA_TYPENAME("BrowsePathResult") /* .typeName */
16138 {0, UA_NODEIDTYPE_NUMERIC, {549LU}}, /* .typeId */
16139 {0, UA_NODEIDTYPE_NUMERIC, {551LU}}, /* .binaryEncodingId */
16140 sizeof(UA_BrowsePathResult), /* .memSize */
16141 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16142 false, /* .pointerFree */
16143 false, /* .overlayable */
16144 2, /* .membersSize */
16145 BrowsePathResult_members /* .members */
16146},
16147/* TranslateBrowsePathsToNodeIdsRequest */
16148{
16149 UA_TYPENAME("TranslateBrowsePathsToNodeIdsRequest") /* .typeName */
16150 {0, UA_NODEIDTYPE_NUMERIC, {552LU}}, /* .typeId */
16151 {0, UA_NODEIDTYPE_NUMERIC, {554LU}}, /* .binaryEncodingId */
16152 sizeof(UA_TranslateBrowsePathsToNodeIdsRequest), /* .memSize */
16153 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16154 false, /* .pointerFree */
16155 false, /* .overlayable */
16156 2, /* .membersSize */
16157 TranslateBrowsePathsToNodeIdsRequest_members /* .members */
16158},
16159/* TranslateBrowsePathsToNodeIdsResponse */
16160{
16161 UA_TYPENAME("TranslateBrowsePathsToNodeIdsResponse") /* .typeName */
16162 {0, UA_NODEIDTYPE_NUMERIC, {555LU}}, /* .typeId */
16163 {0, UA_NODEIDTYPE_NUMERIC, {557LU}}, /* .binaryEncodingId */
16164 sizeof(UA_TranslateBrowsePathsToNodeIdsResponse), /* .memSize */
16165 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16166 false, /* .pointerFree */
16167 false, /* .overlayable */
16168 3, /* .membersSize */
16169 TranslateBrowsePathsToNodeIdsResponse_members /* .members */
16170},
16171/* RegisterNodesRequest */
16172{
16173 UA_TYPENAME("RegisterNodesRequest") /* .typeName */
16174 {0, UA_NODEIDTYPE_NUMERIC, {558LU}}, /* .typeId */
16175 {0, UA_NODEIDTYPE_NUMERIC, {560LU}}, /* .binaryEncodingId */
16176 sizeof(UA_RegisterNodesRequest), /* .memSize */
16177 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16178 false, /* .pointerFree */
16179 false, /* .overlayable */
16180 2, /* .membersSize */
16181 RegisterNodesRequest_members /* .members */
16182},
16183/* RegisterNodesResponse */
16184{
16185 UA_TYPENAME("RegisterNodesResponse") /* .typeName */
16186 {0, UA_NODEIDTYPE_NUMERIC, {561LU}}, /* .typeId */
16187 {0, UA_NODEIDTYPE_NUMERIC, {563LU}}, /* .binaryEncodingId */
16188 sizeof(UA_RegisterNodesResponse), /* .memSize */
16189 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16190 false, /* .pointerFree */
16191 false, /* .overlayable */
16192 2, /* .membersSize */
16193 RegisterNodesResponse_members /* .members */
16194},
16195/* UnregisterNodesRequest */
16196{
16197 UA_TYPENAME("UnregisterNodesRequest") /* .typeName */
16198 {0, UA_NODEIDTYPE_NUMERIC, {564LU}}, /* .typeId */
16199 {0, UA_NODEIDTYPE_NUMERIC, {566LU}}, /* .binaryEncodingId */
16200 sizeof(UA_UnregisterNodesRequest), /* .memSize */
16201 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16202 false, /* .pointerFree */
16203 false, /* .overlayable */
16204 2, /* .membersSize */
16205 UnregisterNodesRequest_members /* .members */
16206},
16207/* UnregisterNodesResponse */
16208{
16209 UA_TYPENAME("UnregisterNodesResponse") /* .typeName */
16210 {0, UA_NODEIDTYPE_NUMERIC, {567LU}}, /* .typeId */
16211 {0, UA_NODEIDTYPE_NUMERIC, {569LU}}, /* .binaryEncodingId */
16212 sizeof(UA_UnregisterNodesResponse), /* .memSize */
16213 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16214 false, /* .pointerFree */
16215 false, /* .overlayable */
16216 1, /* .membersSize */
16217 UnregisterNodesResponse_members /* .members */
16218},
16219/* FilterOperator */
16220{
16221 UA_TYPENAME("FilterOperator") /* .typeName */
16222 {0, UA_NODEIDTYPE_NUMERIC, {576LU}}, /* .typeId */
16223 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16224 sizeof(UA_FilterOperator), /* .memSize */
16225 UA_DATATYPEKIND_ENUM, /* .typeKind */
16226 true, /* .pointerFree */
16227 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16228 0, /* .membersSize */
16229 FilterOperator_members /* .members */
16230},
16231/* ContentFilterElement */
16232{
16233 UA_TYPENAME("ContentFilterElement") /* .typeName */
16234 {0, UA_NODEIDTYPE_NUMERIC, {583LU}}, /* .typeId */
16235 {0, UA_NODEIDTYPE_NUMERIC, {585LU}}, /* .binaryEncodingId */
16236 sizeof(UA_ContentFilterElement), /* .memSize */
16237 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16238 false, /* .pointerFree */
16239 false, /* .overlayable */
16240 2, /* .membersSize */
16241 ContentFilterElement_members /* .members */
16242},
16243/* ContentFilter */
16244{
16245 UA_TYPENAME("ContentFilter") /* .typeName */
16246 {0, UA_NODEIDTYPE_NUMERIC, {586LU}}, /* .typeId */
16247 {0, UA_NODEIDTYPE_NUMERIC, {588LU}}, /* .binaryEncodingId */
16248 sizeof(UA_ContentFilter), /* .memSize */
16249 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16250 false, /* .pointerFree */
16251 false, /* .overlayable */
16252 1, /* .membersSize */
16253 ContentFilter_members /* .members */
16254},
16255/* ElementOperand */
16256{
16257 UA_TYPENAME("ElementOperand") /* .typeName */
16258 {0, UA_NODEIDTYPE_NUMERIC, {592LU}}, /* .typeId */
16259 {0, UA_NODEIDTYPE_NUMERIC, {594LU}}, /* .binaryEncodingId */
16260 sizeof(UA_ElementOperand), /* .memSize */
16261 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16262 true, /* .pointerFree */
16263 false, /* .overlayable */
16264 1, /* .membersSize */
16265 ElementOperand_members /* .members */
16266},
16267/* LiteralOperand */
16268{
16269 UA_TYPENAME("LiteralOperand") /* .typeName */
16270 {0, UA_NODEIDTYPE_NUMERIC, {595LU}}, /* .typeId */
16271 {0, UA_NODEIDTYPE_NUMERIC, {597LU}}, /* .binaryEncodingId */
16272 sizeof(UA_LiteralOperand), /* .memSize */
16273 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16274 false, /* .pointerFree */
16275 false, /* .overlayable */
16276 1, /* .membersSize */
16277 LiteralOperand_members /* .members */
16278},
16279/* AttributeOperand */
16280{
16281 UA_TYPENAME("AttributeOperand") /* .typeName */
16282 {0, UA_NODEIDTYPE_NUMERIC, {598LU}}, /* .typeId */
16283 {0, UA_NODEIDTYPE_NUMERIC, {600LU}}, /* .binaryEncodingId */
16284 sizeof(UA_AttributeOperand), /* .memSize */
16285 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16286 false, /* .pointerFree */
16287 false, /* .overlayable */
16288 5, /* .membersSize */
16289 AttributeOperand_members /* .members */
16290},
16291/* SimpleAttributeOperand */
16292{
16293 UA_TYPENAME("SimpleAttributeOperand") /* .typeName */
16294 {0, UA_NODEIDTYPE_NUMERIC, {601LU}}, /* .typeId */
16295 {0, UA_NODEIDTYPE_NUMERIC, {603LU}}, /* .binaryEncodingId */
16296 sizeof(UA_SimpleAttributeOperand), /* .memSize */
16297 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16298 false, /* .pointerFree */
16299 false, /* .overlayable */
16300 4, /* .membersSize */
16301 SimpleAttributeOperand_members /* .members */
16302},
16303/* ContentFilterElementResult */
16304{
16305 UA_TYPENAME("ContentFilterElementResult") /* .typeName */
16306 {0, UA_NODEIDTYPE_NUMERIC, {604LU}}, /* .typeId */
16307 {0, UA_NODEIDTYPE_NUMERIC, {606LU}}, /* .binaryEncodingId */
16308 sizeof(UA_ContentFilterElementResult), /* .memSize */
16309 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16310 false, /* .pointerFree */
16311 false, /* .overlayable */
16312 3, /* .membersSize */
16313 ContentFilterElementResult_members /* .members */
16314},
16315/* ContentFilterResult */
16316{
16317 UA_TYPENAME("ContentFilterResult") /* .typeName */
16318 {0, UA_NODEIDTYPE_NUMERIC, {607LU}}, /* .typeId */
16319 {0, UA_NODEIDTYPE_NUMERIC, {609LU}}, /* .binaryEncodingId */
16320 sizeof(UA_ContentFilterResult), /* .memSize */
16321 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16322 false, /* .pointerFree */
16323 false, /* .overlayable */
16324 2, /* .membersSize */
16325 ContentFilterResult_members /* .members */
16326},
16327/* TimestampsToReturn */
16328{
16329 UA_TYPENAME("TimestampsToReturn") /* .typeName */
16330 {0, UA_NODEIDTYPE_NUMERIC, {625LU}}, /* .typeId */
16331 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16332 sizeof(UA_TimestampsToReturn), /* .memSize */
16333 UA_DATATYPEKIND_ENUM, /* .typeKind */
16334 true, /* .pointerFree */
16335 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16336 0, /* .membersSize */
16337 TimestampsToReturn_members /* .members */
16338},
16339/* ReadValueId */
16340{
16341 UA_TYPENAME("ReadValueId") /* .typeName */
16342 {0, UA_NODEIDTYPE_NUMERIC, {626LU}}, /* .typeId */
16343 {0, UA_NODEIDTYPE_NUMERIC, {628LU}}, /* .binaryEncodingId */
16344 sizeof(UA_ReadValueId), /* .memSize */
16345 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16346 false, /* .pointerFree */
16347 false, /* .overlayable */
16348 4, /* .membersSize */
16349 ReadValueId_members /* .members */
16350},
16351/* ReadRequest */
16352{
16353 UA_TYPENAME("ReadRequest") /* .typeName */
16354 {0, UA_NODEIDTYPE_NUMERIC, {629LU}}, /* .typeId */
16355 {0, UA_NODEIDTYPE_NUMERIC, {631LU}}, /* .binaryEncodingId */
16356 sizeof(UA_ReadRequest), /* .memSize */
16357 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16358 false, /* .pointerFree */
16359 false, /* .overlayable */
16360 4, /* .membersSize */
16361 ReadRequest_members /* .members */
16362},
16363/* ReadResponse */
16364{
16365 UA_TYPENAME("ReadResponse") /* .typeName */
16366 {0, UA_NODEIDTYPE_NUMERIC, {632LU}}, /* .typeId */
16367 {0, UA_NODEIDTYPE_NUMERIC, {634LU}}, /* .binaryEncodingId */
16368 sizeof(UA_ReadResponse), /* .memSize */
16369 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16370 false, /* .pointerFree */
16371 false, /* .overlayable */
16372 3, /* .membersSize */
16373 ReadResponse_members /* .members */
16374},
16375/* HistoryReadValueId */
16376{
16377 UA_TYPENAME("HistoryReadValueId") /* .typeName */
16378 {0, UA_NODEIDTYPE_NUMERIC, {635LU}}, /* .typeId */
16379 {0, UA_NODEIDTYPE_NUMERIC, {637LU}}, /* .binaryEncodingId */
16380 sizeof(UA_HistoryReadValueId), /* .memSize */
16381 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16382 false, /* .pointerFree */
16383 false, /* .overlayable */
16384 4, /* .membersSize */
16385 HistoryReadValueId_members /* .members */
16386},
16387/* HistoryReadResult */
16388{
16389 UA_TYPENAME("HistoryReadResult") /* .typeName */
16390 {0, UA_NODEIDTYPE_NUMERIC, {638LU}}, /* .typeId */
16391 {0, UA_NODEIDTYPE_NUMERIC, {640LU}}, /* .binaryEncodingId */
16392 sizeof(UA_HistoryReadResult), /* .memSize */
16393 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16394 false, /* .pointerFree */
16395 false, /* .overlayable */
16396 3, /* .membersSize */
16397 HistoryReadResult_members /* .members */
16398},
16399/* ReadRawModifiedDetails */
16400{
16401 UA_TYPENAME("ReadRawModifiedDetails") /* .typeName */
16402 {0, UA_NODEIDTYPE_NUMERIC, {647LU}}, /* .typeId */
16403 {0, UA_NODEIDTYPE_NUMERIC, {649LU}}, /* .binaryEncodingId */
16404 sizeof(UA_ReadRawModifiedDetails), /* .memSize */
16405 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16406 true, /* .pointerFree */
16407 false, /* .overlayable */
16408 5, /* .membersSize */
16409 ReadRawModifiedDetails_members /* .members */
16410},
16411/* ReadAtTimeDetails */
16412{
16413 UA_TYPENAME("ReadAtTimeDetails") /* .typeName */
16414 {0, UA_NODEIDTYPE_NUMERIC, {653LU}}, /* .typeId */
16415 {0, UA_NODEIDTYPE_NUMERIC, {655LU}}, /* .binaryEncodingId */
16416 sizeof(UA_ReadAtTimeDetails), /* .memSize */
16417 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16418 false, /* .pointerFree */
16419 false, /* .overlayable */
16420 2, /* .membersSize */
16421 ReadAtTimeDetails_members /* .members */
16422},
16423/* HistoryData */
16424{
16425 UA_TYPENAME("HistoryData") /* .typeName */
16426 {0, UA_NODEIDTYPE_NUMERIC, {656LU}}, /* .typeId */
16427 {0, UA_NODEIDTYPE_NUMERIC, {658LU}}, /* .binaryEncodingId */
16428 sizeof(UA_HistoryData), /* .memSize */
16429 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16430 false, /* .pointerFree */
16431 false, /* .overlayable */
16432 1, /* .membersSize */
16433 HistoryData_members /* .members */
16434},
16435/* HistoryReadRequest */
16436{
16437 UA_TYPENAME("HistoryReadRequest") /* .typeName */
16438 {0, UA_NODEIDTYPE_NUMERIC, {662LU}}, /* .typeId */
16439 {0, UA_NODEIDTYPE_NUMERIC, {664LU}}, /* .binaryEncodingId */
16440 sizeof(UA_HistoryReadRequest), /* .memSize */
16441 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16442 false, /* .pointerFree */
16443 false, /* .overlayable */
16444 5, /* .membersSize */
16445 HistoryReadRequest_members /* .members */
16446},
16447/* HistoryReadResponse */
16448{
16449 UA_TYPENAME("HistoryReadResponse") /* .typeName */
16450 {0, UA_NODEIDTYPE_NUMERIC, {665LU}}, /* .typeId */
16451 {0, UA_NODEIDTYPE_NUMERIC, {667LU}}, /* .binaryEncodingId */
16452 sizeof(UA_HistoryReadResponse), /* .memSize */
16453 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16454 false, /* .pointerFree */
16455 false, /* .overlayable */
16456 3, /* .membersSize */
16457 HistoryReadResponse_members /* .members */
16458},
16459/* WriteValue */
16460{
16461 UA_TYPENAME("WriteValue") /* .typeName */
16462 {0, UA_NODEIDTYPE_NUMERIC, {668LU}}, /* .typeId */
16463 {0, UA_NODEIDTYPE_NUMERIC, {670LU}}, /* .binaryEncodingId */
16464 sizeof(UA_WriteValue), /* .memSize */
16465 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16466 false, /* .pointerFree */
16467 false, /* .overlayable */
16468 4, /* .membersSize */
16469 WriteValue_members /* .members */
16470},
16471/* WriteRequest */
16472{
16473 UA_TYPENAME("WriteRequest") /* .typeName */
16474 {0, UA_NODEIDTYPE_NUMERIC, {671LU}}, /* .typeId */
16475 {0, UA_NODEIDTYPE_NUMERIC, {673LU}}, /* .binaryEncodingId */
16476 sizeof(UA_WriteRequest), /* .memSize */
16477 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16478 false, /* .pointerFree */
16479 false, /* .overlayable */
16480 2, /* .membersSize */
16481 WriteRequest_members /* .members */
16482},
16483/* WriteResponse */
16484{
16485 UA_TYPENAME("WriteResponse") /* .typeName */
16486 {0, UA_NODEIDTYPE_NUMERIC, {674LU}}, /* .typeId */
16487 {0, UA_NODEIDTYPE_NUMERIC, {676LU}}, /* .binaryEncodingId */
16488 sizeof(UA_WriteResponse), /* .memSize */
16489 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16490 false, /* .pointerFree */
16491 false, /* .overlayable */
16492 3, /* .membersSize */
16493 WriteResponse_members /* .members */
16494},
16495/* HistoryUpdateType */
16496{
16497 UA_TYPENAME("HistoryUpdateType") /* .typeName */
16498 {0, UA_NODEIDTYPE_NUMERIC, {11234LU}}, /* .typeId */
16499 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16500 sizeof(UA_HistoryUpdateType), /* .memSize */
16501 UA_DATATYPEKIND_ENUM, /* .typeKind */
16502 true, /* .pointerFree */
16503 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16504 0, /* .membersSize */
16505 HistoryUpdateType_members /* .members */
16506},
16507/* PerformUpdateType */
16508{
16509 UA_TYPENAME("PerformUpdateType") /* .typeName */
16510 {0, UA_NODEIDTYPE_NUMERIC, {11293LU}}, /* .typeId */
16511 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16512 sizeof(UA_PerformUpdateType), /* .memSize */
16513 UA_DATATYPEKIND_ENUM, /* .typeKind */
16514 true, /* .pointerFree */
16515 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16516 0, /* .membersSize */
16517 PerformUpdateType_members /* .members */
16518},
16519/* UpdateDataDetails */
16520{
16521 UA_TYPENAME("UpdateDataDetails") /* .typeName */
16522 {0, UA_NODEIDTYPE_NUMERIC, {680LU}}, /* .typeId */
16523 {0, UA_NODEIDTYPE_NUMERIC, {682LU}}, /* .binaryEncodingId */
16524 sizeof(UA_UpdateDataDetails), /* .memSize */
16525 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16526 false, /* .pointerFree */
16527 false, /* .overlayable */
16528 3, /* .membersSize */
16529 UpdateDataDetails_members /* .members */
16530},
16531/* DeleteRawModifiedDetails */
16532{
16533 UA_TYPENAME("DeleteRawModifiedDetails") /* .typeName */
16534 {0, UA_NODEIDTYPE_NUMERIC, {686LU}}, /* .typeId */
16535 {0, UA_NODEIDTYPE_NUMERIC, {688LU}}, /* .binaryEncodingId */
16536 sizeof(UA_DeleteRawModifiedDetails), /* .memSize */
16537 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16538 false, /* .pointerFree */
16539 false, /* .overlayable */
16540 4, /* .membersSize */
16541 DeleteRawModifiedDetails_members /* .members */
16542},
16543/* HistoryUpdateResult */
16544{
16545 UA_TYPENAME("HistoryUpdateResult") /* .typeName */
16546 {0, UA_NODEIDTYPE_NUMERIC, {695LU}}, /* .typeId */
16547 {0, UA_NODEIDTYPE_NUMERIC, {697LU}}, /* .binaryEncodingId */
16548 sizeof(UA_HistoryUpdateResult), /* .memSize */
16549 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16550 false, /* .pointerFree */
16551 false, /* .overlayable */
16552 3, /* .membersSize */
16553 HistoryUpdateResult_members /* .members */
16554},
16555/* HistoryUpdateRequest */
16556{
16557 UA_TYPENAME("HistoryUpdateRequest") /* .typeName */
16558 {0, UA_NODEIDTYPE_NUMERIC, {698LU}}, /* .typeId */
16559 {0, UA_NODEIDTYPE_NUMERIC, {700LU}}, /* .binaryEncodingId */
16560 sizeof(UA_HistoryUpdateRequest), /* .memSize */
16561 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16562 false, /* .pointerFree */
16563 false, /* .overlayable */
16564 2, /* .membersSize */
16565 HistoryUpdateRequest_members /* .members */
16566},
16567/* HistoryUpdateResponse */
16568{
16569 UA_TYPENAME("HistoryUpdateResponse") /* .typeName */
16570 {0, UA_NODEIDTYPE_NUMERIC, {701LU}}, /* .typeId */
16571 {0, UA_NODEIDTYPE_NUMERIC, {703LU}}, /* .binaryEncodingId */
16572 sizeof(UA_HistoryUpdateResponse), /* .memSize */
16573 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16574 false, /* .pointerFree */
16575 false, /* .overlayable */
16576 3, /* .membersSize */
16577 HistoryUpdateResponse_members /* .members */
16578},
16579/* CallMethodRequest */
16580{
16581 UA_TYPENAME("CallMethodRequest") /* .typeName */
16582 {0, UA_NODEIDTYPE_NUMERIC, {704LU}}, /* .typeId */
16583 {0, UA_NODEIDTYPE_NUMERIC, {706LU}}, /* .binaryEncodingId */
16584 sizeof(UA_CallMethodRequest), /* .memSize */
16585 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16586 false, /* .pointerFree */
16587 false, /* .overlayable */
16588 3, /* .membersSize */
16589 CallMethodRequest_members /* .members */
16590},
16591/* CallMethodResult */
16592{
16593 UA_TYPENAME("CallMethodResult") /* .typeName */
16594 {0, UA_NODEIDTYPE_NUMERIC, {707LU}}, /* .typeId */
16595 {0, UA_NODEIDTYPE_NUMERIC, {709LU}}, /* .binaryEncodingId */
16596 sizeof(UA_CallMethodResult), /* .memSize */
16597 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16598 false, /* .pointerFree */
16599 false, /* .overlayable */
16600 4, /* .membersSize */
16601 CallMethodResult_members /* .members */
16602},
16603/* CallRequest */
16604{
16605 UA_TYPENAME("CallRequest") /* .typeName */
16606 {0, UA_NODEIDTYPE_NUMERIC, {710LU}}, /* .typeId */
16607 {0, UA_NODEIDTYPE_NUMERIC, {712LU}}, /* .binaryEncodingId */
16608 sizeof(UA_CallRequest), /* .memSize */
16609 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16610 false, /* .pointerFree */
16611 false, /* .overlayable */
16612 2, /* .membersSize */
16613 CallRequest_members /* .members */
16614},
16615/* CallResponse */
16616{
16617 UA_TYPENAME("CallResponse") /* .typeName */
16618 {0, UA_NODEIDTYPE_NUMERIC, {713LU}}, /* .typeId */
16619 {0, UA_NODEIDTYPE_NUMERIC, {715LU}}, /* .binaryEncodingId */
16620 sizeof(UA_CallResponse), /* .memSize */
16621 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16622 false, /* .pointerFree */
16623 false, /* .overlayable */
16624 3, /* .membersSize */
16625 CallResponse_members /* .members */
16626},
16627/* MonitoringMode */
16628{
16629 UA_TYPENAME("MonitoringMode") /* .typeName */
16630 {0, UA_NODEIDTYPE_NUMERIC, {716LU}}, /* .typeId */
16631 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16632 sizeof(UA_MonitoringMode), /* .memSize */
16633 UA_DATATYPEKIND_ENUM, /* .typeKind */
16634 true, /* .pointerFree */
16635 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16636 0, /* .membersSize */
16637 MonitoringMode_members /* .members */
16638},
16639/* DataChangeTrigger */
16640{
16641 UA_TYPENAME("DataChangeTrigger") /* .typeName */
16642 {0, UA_NODEIDTYPE_NUMERIC, {717LU}}, /* .typeId */
16643 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16644 sizeof(UA_DataChangeTrigger), /* .memSize */
16645 UA_DATATYPEKIND_ENUM, /* .typeKind */
16646 true, /* .pointerFree */
16647 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16648 0, /* .membersSize */
16649 DataChangeTrigger_members /* .members */
16650},
16651/* DeadbandType */
16652{
16653 UA_TYPENAME("DeadbandType") /* .typeName */
16654 {0, UA_NODEIDTYPE_NUMERIC, {718LU}}, /* .typeId */
16655 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16656 sizeof(UA_DeadbandType), /* .memSize */
16657 UA_DATATYPEKIND_ENUM, /* .typeKind */
16658 true, /* .pointerFree */
16659 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16660 0, /* .membersSize */
16661 DeadbandType_members /* .members */
16662},
16663/* DataChangeFilter */
16664{
16665 UA_TYPENAME("DataChangeFilter") /* .typeName */
16666 {0, UA_NODEIDTYPE_NUMERIC, {722LU}}, /* .typeId */
16667 {0, UA_NODEIDTYPE_NUMERIC, {724LU}}, /* .binaryEncodingId */
16668 sizeof(UA_DataChangeFilter), /* .memSize */
16669 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16670 true, /* .pointerFree */
16671 false, /* .overlayable */
16672 3, /* .membersSize */
16673 DataChangeFilter_members /* .members */
16674},
16675/* EventFilter */
16676{
16677 UA_TYPENAME("EventFilter") /* .typeName */
16678 {0, UA_NODEIDTYPE_NUMERIC, {725LU}}, /* .typeId */
16679 {0, UA_NODEIDTYPE_NUMERIC, {727LU}}, /* .binaryEncodingId */
16680 sizeof(UA_EventFilter), /* .memSize */
16681 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16682 false, /* .pointerFree */
16683 false, /* .overlayable */
16684 2, /* .membersSize */
16685 EventFilter_members /* .members */
16686},
16687/* AggregateConfiguration */
16688{
16689 UA_TYPENAME("AggregateConfiguration") /* .typeName */
16690 {0, UA_NODEIDTYPE_NUMERIC, {948LU}}, /* .typeId */
16691 {0, UA_NODEIDTYPE_NUMERIC, {950LU}}, /* .binaryEncodingId */
16692 sizeof(UA_AggregateConfiguration), /* .memSize */
16693 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16694 true, /* .pointerFree */
16695 false, /* .overlayable */
16696 5, /* .membersSize */
16697 AggregateConfiguration_members /* .members */
16698},
16699/* AggregateFilter */
16700{
16701 UA_TYPENAME("AggregateFilter") /* .typeName */
16702 {0, UA_NODEIDTYPE_NUMERIC, {728LU}}, /* .typeId */
16703 {0, UA_NODEIDTYPE_NUMERIC, {730LU}}, /* .binaryEncodingId */
16704 sizeof(UA_AggregateFilter), /* .memSize */
16705 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16706 false, /* .pointerFree */
16707 false, /* .overlayable */
16708 4, /* .membersSize */
16709 AggregateFilter_members /* .members */
16710},
16711/* EventFilterResult */
16712{
16713 UA_TYPENAME("EventFilterResult") /* .typeName */
16714 {0, UA_NODEIDTYPE_NUMERIC, {734LU}}, /* .typeId */
16715 {0, UA_NODEIDTYPE_NUMERIC, {736LU}}, /* .binaryEncodingId */
16716 sizeof(UA_EventFilterResult), /* .memSize */
16717 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16718 false, /* .pointerFree */
16719 false, /* .overlayable */
16720 3, /* .membersSize */
16721 EventFilterResult_members /* .members */
16722},
16723/* MonitoringParameters */
16724{
16725 UA_TYPENAME("MonitoringParameters") /* .typeName */
16726 {0, UA_NODEIDTYPE_NUMERIC, {740LU}}, /* .typeId */
16727 {0, UA_NODEIDTYPE_NUMERIC, {742LU}}, /* .binaryEncodingId */
16728 sizeof(UA_MonitoringParameters), /* .memSize */
16729 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16730 false, /* .pointerFree */
16731 false, /* .overlayable */
16732 5, /* .membersSize */
16733 MonitoringParameters_members /* .members */
16734},
16735/* MonitoredItemCreateRequest */
16736{
16737 UA_TYPENAME("MonitoredItemCreateRequest") /* .typeName */
16738 {0, UA_NODEIDTYPE_NUMERIC, {743LU}}, /* .typeId */
16739 {0, UA_NODEIDTYPE_NUMERIC, {745LU}}, /* .binaryEncodingId */
16740 sizeof(UA_MonitoredItemCreateRequest), /* .memSize */
16741 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16742 false, /* .pointerFree */
16743 false, /* .overlayable */
16744 3, /* .membersSize */
16745 MonitoredItemCreateRequest_members /* .members */
16746},
16747/* MonitoredItemCreateResult */
16748{
16749 UA_TYPENAME("MonitoredItemCreateResult") /* .typeName */
16750 {0, UA_NODEIDTYPE_NUMERIC, {746LU}}, /* .typeId */
16751 {0, UA_NODEIDTYPE_NUMERIC, {748LU}}, /* .binaryEncodingId */
16752 sizeof(UA_MonitoredItemCreateResult), /* .memSize */
16753 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16754 false, /* .pointerFree */
16755 false, /* .overlayable */
16756 5, /* .membersSize */
16757 MonitoredItemCreateResult_members /* .members */
16758},
16759/* CreateMonitoredItemsRequest */
16760{
16761 UA_TYPENAME("CreateMonitoredItemsRequest") /* .typeName */
16762 {0, UA_NODEIDTYPE_NUMERIC, {749LU}}, /* .typeId */
16763 {0, UA_NODEIDTYPE_NUMERIC, {751LU}}, /* .binaryEncodingId */
16764 sizeof(UA_CreateMonitoredItemsRequest), /* .memSize */
16765 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16766 false, /* .pointerFree */
16767 false, /* .overlayable */
16768 4, /* .membersSize */
16769 CreateMonitoredItemsRequest_members /* .members */
16770},
16771/* CreateMonitoredItemsResponse */
16772{
16773 UA_TYPENAME("CreateMonitoredItemsResponse") /* .typeName */
16774 {0, UA_NODEIDTYPE_NUMERIC, {752LU}}, /* .typeId */
16775 {0, UA_NODEIDTYPE_NUMERIC, {754LU}}, /* .binaryEncodingId */
16776 sizeof(UA_CreateMonitoredItemsResponse), /* .memSize */
16777 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16778 false, /* .pointerFree */
16779 false, /* .overlayable */
16780 3, /* .membersSize */
16781 CreateMonitoredItemsResponse_members /* .members */
16782},
16783/* MonitoredItemModifyRequest */
16784{
16785 UA_TYPENAME("MonitoredItemModifyRequest") /* .typeName */
16786 {0, UA_NODEIDTYPE_NUMERIC, {755LU}}, /* .typeId */
16787 {0, UA_NODEIDTYPE_NUMERIC, {757LU}}, /* .binaryEncodingId */
16788 sizeof(UA_MonitoredItemModifyRequest), /* .memSize */
16789 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16790 false, /* .pointerFree */
16791 false, /* .overlayable */
16792 2, /* .membersSize */
16793 MonitoredItemModifyRequest_members /* .members */
16794},
16795/* MonitoredItemModifyResult */
16796{
16797 UA_TYPENAME("MonitoredItemModifyResult") /* .typeName */
16798 {0, UA_NODEIDTYPE_NUMERIC, {758LU}}, /* .typeId */
16799 {0, UA_NODEIDTYPE_NUMERIC, {760LU}}, /* .binaryEncodingId */
16800 sizeof(UA_MonitoredItemModifyResult), /* .memSize */
16801 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16802 false, /* .pointerFree */
16803 false, /* .overlayable */
16804 4, /* .membersSize */
16805 MonitoredItemModifyResult_members /* .members */
16806},
16807/* ModifyMonitoredItemsRequest */
16808{
16809 UA_TYPENAME("ModifyMonitoredItemsRequest") /* .typeName */
16810 {0, UA_NODEIDTYPE_NUMERIC, {761LU}}, /* .typeId */
16811 {0, UA_NODEIDTYPE_NUMERIC, {763LU}}, /* .binaryEncodingId */
16812 sizeof(UA_ModifyMonitoredItemsRequest), /* .memSize */
16813 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16814 false, /* .pointerFree */
16815 false, /* .overlayable */
16816 4, /* .membersSize */
16817 ModifyMonitoredItemsRequest_members /* .members */
16818},
16819/* ModifyMonitoredItemsResponse */
16820{
16821 UA_TYPENAME("ModifyMonitoredItemsResponse") /* .typeName */
16822 {0, UA_NODEIDTYPE_NUMERIC, {764LU}}, /* .typeId */
16823 {0, UA_NODEIDTYPE_NUMERIC, {766LU}}, /* .binaryEncodingId */
16824 sizeof(UA_ModifyMonitoredItemsResponse), /* .memSize */
16825 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16826 false, /* .pointerFree */
16827 false, /* .overlayable */
16828 3, /* .membersSize */
16829 ModifyMonitoredItemsResponse_members /* .members */
16830},
16831/* SetMonitoringModeRequest */
16832{
16833 UA_TYPENAME("SetMonitoringModeRequest") /* .typeName */
16834 {0, UA_NODEIDTYPE_NUMERIC, {767LU}}, /* .typeId */
16835 {0, UA_NODEIDTYPE_NUMERIC, {769LU}}, /* .binaryEncodingId */
16836 sizeof(UA_SetMonitoringModeRequest), /* .memSize */
16837 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16838 false, /* .pointerFree */
16839 false, /* .overlayable */
16840 4, /* .membersSize */
16841 SetMonitoringModeRequest_members /* .members */
16842},
16843/* SetMonitoringModeResponse */
16844{
16845 UA_TYPENAME("SetMonitoringModeResponse") /* .typeName */
16846 {0, UA_NODEIDTYPE_NUMERIC, {770LU}}, /* .typeId */
16847 {0, UA_NODEIDTYPE_NUMERIC, {772LU}}, /* .binaryEncodingId */
16848 sizeof(UA_SetMonitoringModeResponse), /* .memSize */
16849 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16850 false, /* .pointerFree */
16851 false, /* .overlayable */
16852 3, /* .membersSize */
16853 SetMonitoringModeResponse_members /* .members */
16854},
16855/* SetTriggeringRequest */
16856{
16857 UA_TYPENAME("SetTriggeringRequest") /* .typeName */
16858 {0, UA_NODEIDTYPE_NUMERIC, {773LU}}, /* .typeId */
16859 {0, UA_NODEIDTYPE_NUMERIC, {775LU}}, /* .binaryEncodingId */
16860 sizeof(UA_SetTriggeringRequest), /* .memSize */
16861 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16862 false, /* .pointerFree */
16863 false, /* .overlayable */
16864 5, /* .membersSize */
16865 SetTriggeringRequest_members /* .members */
16866},
16867/* SetTriggeringResponse */
16868{
16869 UA_TYPENAME("SetTriggeringResponse") /* .typeName */
16870 {0, UA_NODEIDTYPE_NUMERIC, {776LU}}, /* .typeId */
16871 {0, UA_NODEIDTYPE_NUMERIC, {778LU}}, /* .binaryEncodingId */
16872 sizeof(UA_SetTriggeringResponse), /* .memSize */
16873 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16874 false, /* .pointerFree */
16875 false, /* .overlayable */
16876 5, /* .membersSize */
16877 SetTriggeringResponse_members /* .members */
16878},
16879/* DeleteMonitoredItemsRequest */
16880{
16881 UA_TYPENAME("DeleteMonitoredItemsRequest") /* .typeName */
16882 {0, UA_NODEIDTYPE_NUMERIC, {779LU}}, /* .typeId */
16883 {0, UA_NODEIDTYPE_NUMERIC, {781LU}}, /* .binaryEncodingId */
16884 sizeof(UA_DeleteMonitoredItemsRequest), /* .memSize */
16885 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16886 false, /* .pointerFree */
16887 false, /* .overlayable */
16888 3, /* .membersSize */
16889 DeleteMonitoredItemsRequest_members /* .members */
16890},
16891/* DeleteMonitoredItemsResponse */
16892{
16893 UA_TYPENAME("DeleteMonitoredItemsResponse") /* .typeName */
16894 {0, UA_NODEIDTYPE_NUMERIC, {782LU}}, /* .typeId */
16895 {0, UA_NODEIDTYPE_NUMERIC, {784LU}}, /* .binaryEncodingId */
16896 sizeof(UA_DeleteMonitoredItemsResponse), /* .memSize */
16897 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16898 false, /* .pointerFree */
16899 false, /* .overlayable */
16900 3, /* .membersSize */
16901 DeleteMonitoredItemsResponse_members /* .members */
16902},
16903/* CreateSubscriptionRequest */
16904{
16905 UA_TYPENAME("CreateSubscriptionRequest") /* .typeName */
16906 {0, UA_NODEIDTYPE_NUMERIC, {785LU}}, /* .typeId */
16907 {0, UA_NODEIDTYPE_NUMERIC, {787LU}}, /* .binaryEncodingId */
16908 sizeof(UA_CreateSubscriptionRequest), /* .memSize */
16909 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16910 false, /* .pointerFree */
16911 false, /* .overlayable */
16912 7, /* .membersSize */
16913 CreateSubscriptionRequest_members /* .members */
16914},
16915/* CreateSubscriptionResponse */
16916{
16917 UA_TYPENAME("CreateSubscriptionResponse") /* .typeName */
16918 {0, UA_NODEIDTYPE_NUMERIC, {788LU}}, /* .typeId */
16919 {0, UA_NODEIDTYPE_NUMERIC, {790LU}}, /* .binaryEncodingId */
16920 sizeof(UA_CreateSubscriptionResponse), /* .memSize */
16921 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16922 false, /* .pointerFree */
16923 false, /* .overlayable */
16924 5, /* .membersSize */
16925 CreateSubscriptionResponse_members /* .members */
16926},
16927/* ModifySubscriptionRequest */
16928{
16929 UA_TYPENAME("ModifySubscriptionRequest") /* .typeName */
16930 {0, UA_NODEIDTYPE_NUMERIC, {791LU}}, /* .typeId */
16931 {0, UA_NODEIDTYPE_NUMERIC, {793LU}}, /* .binaryEncodingId */
16932 sizeof(UA_ModifySubscriptionRequest), /* .memSize */
16933 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16934 false, /* .pointerFree */
16935 false, /* .overlayable */
16936 7, /* .membersSize */
16937 ModifySubscriptionRequest_members /* .members */
16938},
16939/* ModifySubscriptionResponse */
16940{
16941 UA_TYPENAME("ModifySubscriptionResponse") /* .typeName */
16942 {0, UA_NODEIDTYPE_NUMERIC, {794LU}}, /* .typeId */
16943 {0, UA_NODEIDTYPE_NUMERIC, {796LU}}, /* .binaryEncodingId */
16944 sizeof(UA_ModifySubscriptionResponse), /* .memSize */
16945 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16946 false, /* .pointerFree */
16947 false, /* .overlayable */
16948 4, /* .membersSize */
16949 ModifySubscriptionResponse_members /* .members */
16950},
16951/* SetPublishingModeRequest */
16952{
16953 UA_TYPENAME("SetPublishingModeRequest") /* .typeName */
16954 {0, UA_NODEIDTYPE_NUMERIC, {797LU}}, /* .typeId */
16955 {0, UA_NODEIDTYPE_NUMERIC, {799LU}}, /* .binaryEncodingId */
16956 sizeof(UA_SetPublishingModeRequest), /* .memSize */
16957 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16958 false, /* .pointerFree */
16959 false, /* .overlayable */
16960 3, /* .membersSize */
16961 SetPublishingModeRequest_members /* .members */
16962},
16963/* SetPublishingModeResponse */
16964{
16965 UA_TYPENAME("SetPublishingModeResponse") /* .typeName */
16966 {0, UA_NODEIDTYPE_NUMERIC, {800LU}}, /* .typeId */
16967 {0, UA_NODEIDTYPE_NUMERIC, {802LU}}, /* .binaryEncodingId */
16968 sizeof(UA_SetPublishingModeResponse), /* .memSize */
16969 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16970 false, /* .pointerFree */
16971 false, /* .overlayable */
16972 3, /* .membersSize */
16973 SetPublishingModeResponse_members /* .members */
16974},
16975/* NotificationMessage */
16976{
16977 UA_TYPENAME("NotificationMessage") /* .typeName */
16978 {0, UA_NODEIDTYPE_NUMERIC, {803LU}}, /* .typeId */
16979 {0, UA_NODEIDTYPE_NUMERIC, {805LU}}, /* .binaryEncodingId */
16980 sizeof(UA_NotificationMessage), /* .memSize */
16981 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16982 false, /* .pointerFree */
16983 false, /* .overlayable */
16984 3, /* .membersSize */
16985 NotificationMessage_members /* .members */
16986},
16987/* MonitoredItemNotification */
16988{
16989 UA_TYPENAME("MonitoredItemNotification") /* .typeName */
16990 {0, UA_NODEIDTYPE_NUMERIC, {806LU}}, /* .typeId */
16991 {0, UA_NODEIDTYPE_NUMERIC, {808LU}}, /* .binaryEncodingId */
16992 sizeof(UA_MonitoredItemNotification), /* .memSize */
16993 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16994 false, /* .pointerFree */
16995 false, /* .overlayable */
16996 2, /* .membersSize */
16997 MonitoredItemNotification_members /* .members */
16998},
16999/* EventFieldList */
17000{
17001 UA_TYPENAME("EventFieldList") /* .typeName */
17002 {0, UA_NODEIDTYPE_NUMERIC, {917LU}}, /* .typeId */
17003 {0, UA_NODEIDTYPE_NUMERIC, {919LU}}, /* .binaryEncodingId */
17004 sizeof(UA_EventFieldList), /* .memSize */
17005 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17006 false, /* .pointerFree */
17007 false, /* .overlayable */
17008 2, /* .membersSize */
17009 EventFieldList_members /* .members */
17010},
17011/* HistoryEventFieldList */
17012{
17013 UA_TYPENAME("HistoryEventFieldList") /* .typeName */
17014 {0, UA_NODEIDTYPE_NUMERIC, {920LU}}, /* .typeId */
17015 {0, UA_NODEIDTYPE_NUMERIC, {922LU}}, /* .binaryEncodingId */
17016 sizeof(UA_HistoryEventFieldList), /* .memSize */
17017 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17018 false, /* .pointerFree */
17019 false, /* .overlayable */
17020 1, /* .membersSize */
17021 HistoryEventFieldList_members /* .members */
17022},
17023/* StatusChangeNotification */
17024{
17025 UA_TYPENAME("StatusChangeNotification") /* .typeName */
17026 {0, UA_NODEIDTYPE_NUMERIC, {818LU}}, /* .typeId */
17027 {0, UA_NODEIDTYPE_NUMERIC, {820LU}}, /* .binaryEncodingId */
17028 sizeof(UA_StatusChangeNotification), /* .memSize */
17029 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17030 false, /* .pointerFree */
17031 false, /* .overlayable */
17032 2, /* .membersSize */
17033 StatusChangeNotification_members /* .members */
17034},
17035/* SubscriptionAcknowledgement */
17036{
17037 UA_TYPENAME("SubscriptionAcknowledgement") /* .typeName */
17038 {0, UA_NODEIDTYPE_NUMERIC, {821LU}}, /* .typeId */
17039 {0, UA_NODEIDTYPE_NUMERIC, {823LU}}, /* .binaryEncodingId */
17040 sizeof(UA_SubscriptionAcknowledgement), /* .memSize */
17041 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17042 true, /* .pointerFree */
17043 false, /* .overlayable */
17044 2, /* .membersSize */
17045 SubscriptionAcknowledgement_members /* .members */
17046},
17047/* PublishRequest */
17048{
17049 UA_TYPENAME("PublishRequest") /* .typeName */
17050 {0, UA_NODEIDTYPE_NUMERIC, {824LU}}, /* .typeId */
17051 {0, UA_NODEIDTYPE_NUMERIC, {826LU}}, /* .binaryEncodingId */
17052 sizeof(UA_PublishRequest), /* .memSize */
17053 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17054 false, /* .pointerFree */
17055 false, /* .overlayable */
17056 2, /* .membersSize */
17057 PublishRequest_members /* .members */
17058},
17059/* PublishResponse */
17060{
17061 UA_TYPENAME("PublishResponse") /* .typeName */
17062 {0, UA_NODEIDTYPE_NUMERIC, {827LU}}, /* .typeId */
17063 {0, UA_NODEIDTYPE_NUMERIC, {829LU}}, /* .binaryEncodingId */
17064 sizeof(UA_PublishResponse), /* .memSize */
17065 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17066 false, /* .pointerFree */
17067 false, /* .overlayable */
17068 7, /* .membersSize */
17069 PublishResponse_members /* .members */
17070},
17071/* RepublishRequest */
17072{
17073 UA_TYPENAME("RepublishRequest") /* .typeName */
17074 {0, UA_NODEIDTYPE_NUMERIC, {830LU}}, /* .typeId */
17075 {0, UA_NODEIDTYPE_NUMERIC, {832LU}}, /* .binaryEncodingId */
17076 sizeof(UA_RepublishRequest), /* .memSize */
17077 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17078 false, /* .pointerFree */
17079 false, /* .overlayable */
17080 3, /* .membersSize */
17081 RepublishRequest_members /* .members */
17082},
17083/* RepublishResponse */
17084{
17085 UA_TYPENAME("RepublishResponse") /* .typeName */
17086 {0, UA_NODEIDTYPE_NUMERIC, {833LU}}, /* .typeId */
17087 {0, UA_NODEIDTYPE_NUMERIC, {835LU}}, /* .binaryEncodingId */
17088 sizeof(UA_RepublishResponse), /* .memSize */
17089 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17090 false, /* .pointerFree */
17091 false, /* .overlayable */
17092 2, /* .membersSize */
17093 RepublishResponse_members /* .members */
17094},
17095/* TransferResult */
17096{
17097 UA_TYPENAME("TransferResult") /* .typeName */
17098 {0, UA_NODEIDTYPE_NUMERIC, {836LU}}, /* .typeId */
17099 {0, UA_NODEIDTYPE_NUMERIC, {838LU}}, /* .binaryEncodingId */
17100 sizeof(UA_TransferResult), /* .memSize */
17101 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17102 false, /* .pointerFree */
17103 false, /* .overlayable */
17104 2, /* .membersSize */
17105 TransferResult_members /* .members */
17106},
17107/* TransferSubscriptionsRequest */
17108{
17109 UA_TYPENAME("TransferSubscriptionsRequest") /* .typeName */
17110 {0, UA_NODEIDTYPE_NUMERIC, {839LU}}, /* .typeId */
17111 {0, UA_NODEIDTYPE_NUMERIC, {841LU}}, /* .binaryEncodingId */
17112 sizeof(UA_TransferSubscriptionsRequest), /* .memSize */
17113 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17114 false, /* .pointerFree */
17115 false, /* .overlayable */
17116 3, /* .membersSize */
17117 TransferSubscriptionsRequest_members /* .members */
17118},
17119/* TransferSubscriptionsResponse */
17120{
17121 UA_TYPENAME("TransferSubscriptionsResponse") /* .typeName */
17122 {0, UA_NODEIDTYPE_NUMERIC, {842LU}}, /* .typeId */
17123 {0, UA_NODEIDTYPE_NUMERIC, {844LU}}, /* .binaryEncodingId */
17124 sizeof(UA_TransferSubscriptionsResponse), /* .memSize */
17125 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17126 false, /* .pointerFree */
17127 false, /* .overlayable */
17128 3, /* .membersSize */
17129 TransferSubscriptionsResponse_members /* .members */
17130},
17131/* DeleteSubscriptionsRequest */
17132{
17133 UA_TYPENAME("DeleteSubscriptionsRequest") /* .typeName */
17134 {0, UA_NODEIDTYPE_NUMERIC, {845LU}}, /* .typeId */
17135 {0, UA_NODEIDTYPE_NUMERIC, {847LU}}, /* .binaryEncodingId */
17136 sizeof(UA_DeleteSubscriptionsRequest), /* .memSize */
17137 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17138 false, /* .pointerFree */
17139 false, /* .overlayable */
17140 2, /* .membersSize */
17141 DeleteSubscriptionsRequest_members /* .members */
17142},
17143/* DeleteSubscriptionsResponse */
17144{
17145 UA_TYPENAME("DeleteSubscriptionsResponse") /* .typeName */
17146 {0, UA_NODEIDTYPE_NUMERIC, {848LU}}, /* .typeId */
17147 {0, UA_NODEIDTYPE_NUMERIC, {850LU}}, /* .binaryEncodingId */
17148 sizeof(UA_DeleteSubscriptionsResponse), /* .memSize */
17149 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17150 false, /* .pointerFree */
17151 false, /* .overlayable */
17152 3, /* .membersSize */
17153 DeleteSubscriptionsResponse_members /* .members */
17154},
17155/* BuildInfo */
17156{
17157 UA_TYPENAME("BuildInfo") /* .typeName */
17158 {0, UA_NODEIDTYPE_NUMERIC, {338LU}}, /* .typeId */
17159 {0, UA_NODEIDTYPE_NUMERIC, {340LU}}, /* .binaryEncodingId */
17160 sizeof(UA_BuildInfo), /* .memSize */
17161 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17162 false, /* .pointerFree */
17163 false, /* .overlayable */
17164 6, /* .membersSize */
17165 BuildInfo_members /* .members */
17166},
17167/* RedundancySupport */
17168{
17169 UA_TYPENAME("RedundancySupport") /* .typeName */
17170 {0, UA_NODEIDTYPE_NUMERIC, {851LU}}, /* .typeId */
17171 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17172 sizeof(UA_RedundancySupport), /* .memSize */
17173 UA_DATATYPEKIND_ENUM, /* .typeKind */
17174 true, /* .pointerFree */
17175 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17176 0, /* .membersSize */
17177 RedundancySupport_members /* .members */
17178},
17179/* ServerState */
17180{
17181 UA_TYPENAME("ServerState") /* .typeName */
17182 {0, UA_NODEIDTYPE_NUMERIC, {852LU}}, /* .typeId */
17183 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17184 sizeof(UA_ServerState), /* .memSize */
17185 UA_DATATYPEKIND_ENUM, /* .typeKind */
17186 true, /* .pointerFree */
17187 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17188 0, /* .membersSize */
17189 ServerState_members /* .members */
17190},
17191/* ServerDiagnosticsSummaryDataType */
17192{
17193 UA_TYPENAME("ServerDiagnosticsSummaryDataType") /* .typeName */
17194 {0, UA_NODEIDTYPE_NUMERIC, {859LU}}, /* .typeId */
17195 {0, UA_NODEIDTYPE_NUMERIC, {861LU}}, /* .binaryEncodingId */
17196 sizeof(UA_ServerDiagnosticsSummaryDataType), /* .memSize */
17197 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17198 true, /* .pointerFree */
17199 false, /* .overlayable */
17200 12, /* .membersSize */
17201 ServerDiagnosticsSummaryDataType_members /* .members */
17202},
17203/* ServerStatusDataType */
17204{
17205 UA_TYPENAME("ServerStatusDataType") /* .typeName */
17206 {0, UA_NODEIDTYPE_NUMERIC, {862LU}}, /* .typeId */
17207 {0, UA_NODEIDTYPE_NUMERIC, {864LU}}, /* .binaryEncodingId */
17208 sizeof(UA_ServerStatusDataType), /* .memSize */
17209 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17210 false, /* .pointerFree */
17211 false, /* .overlayable */
17212 6, /* .membersSize */
17213 ServerStatusDataType_members /* .members */
17214},
17215/* Range */
17216{
17217 UA_TYPENAME("Range") /* .typeName */
17218 {0, UA_NODEIDTYPE_NUMERIC, {884LU}}, /* .typeId */
17219 {0, UA_NODEIDTYPE_NUMERIC, {886LU}}, /* .binaryEncodingId */
17220 sizeof(UA_Range), /* .memSize */
17221 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17222 true, /* .pointerFree */
17223 false, /* .overlayable */
17224 2, /* .membersSize */
17225 Range_members /* .members */
17226},
17227/* EUInformation */
17228{
17229 UA_TYPENAME("EUInformation") /* .typeName */
17230 {0, UA_NODEIDTYPE_NUMERIC, {887LU}}, /* .typeId */
17231 {0, UA_NODEIDTYPE_NUMERIC, {889LU}}, /* .binaryEncodingId */
17232 sizeof(UA_EUInformation), /* .memSize */
17233 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17234 false, /* .pointerFree */
17235 false, /* .overlayable */
17236 4, /* .membersSize */
17237 EUInformation_members /* .members */
17238},
17239/* AxisScaleEnumeration */
17240{
17241 UA_TYPENAME("AxisScaleEnumeration") /* .typeName */
17242 {0, UA_NODEIDTYPE_NUMERIC, {12077LU}}, /* .typeId */
17243 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17244 sizeof(UA_AxisScaleEnumeration), /* .memSize */
17245 UA_DATATYPEKIND_ENUM, /* .typeKind */
17246 true, /* .pointerFree */
17247 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17248 0, /* .membersSize */
17249 AxisScaleEnumeration_members /* .members */
17250},
17251/* ComplexNumberType */
17252{
17253 UA_TYPENAME("ComplexNumberType") /* .typeName */
17254 {0, UA_NODEIDTYPE_NUMERIC, {12171LU}}, /* .typeId */
17255 {0, UA_NODEIDTYPE_NUMERIC, {12181LU}}, /* .binaryEncodingId */
17256 sizeof(UA_ComplexNumberType), /* .memSize */
17257 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17258 true, /* .pointerFree */
17259 false, /* .overlayable */
17260 2, /* .membersSize */
17261 ComplexNumberType_members /* .members */
17262},
17263/* DoubleComplexNumberType */
17264{
17265 UA_TYPENAME("DoubleComplexNumberType") /* .typeName */
17266 {0, UA_NODEIDTYPE_NUMERIC, {12172LU}}, /* .typeId */
17267 {0, UA_NODEIDTYPE_NUMERIC, {12182LU}}, /* .binaryEncodingId */
17268 sizeof(UA_DoubleComplexNumberType), /* .memSize */
17269 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17270 true, /* .pointerFree */
17271 false, /* .overlayable */
17272 2, /* .membersSize */
17273 DoubleComplexNumberType_members /* .members */
17274},
17275/* AxisInformation */
17276{
17277 UA_TYPENAME("AxisInformation") /* .typeName */
17278 {0, UA_NODEIDTYPE_NUMERIC, {12079LU}}, /* .typeId */
17279 {0, UA_NODEIDTYPE_NUMERIC, {12089LU}}, /* .binaryEncodingId */
17280 sizeof(UA_AxisInformation), /* .memSize */
17281 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17282 false, /* .pointerFree */
17283 false, /* .overlayable */
17284 5, /* .membersSize */
17285 AxisInformation_members /* .members */
17286},
17287/* XVType */
17288{
17289 UA_TYPENAME("XVType") /* .typeName */
17290 {0, UA_NODEIDTYPE_NUMERIC, {12080LU}}, /* .typeId */
17291 {0, UA_NODEIDTYPE_NUMERIC, {12090LU}}, /* .binaryEncodingId */
17292 sizeof(UA_XVType), /* .memSize */
17293 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17294 true, /* .pointerFree */
17295 false, /* .overlayable */
17296 2, /* .membersSize */
17297 XVType_members /* .members */
17298},
17299/* EnumDefinition */
17300{
17301 UA_TYPENAME("EnumDefinition") /* .typeName */
17302 {0, UA_NODEIDTYPE_NUMERIC, {100LU}}, /* .typeId */
17303 {0, UA_NODEIDTYPE_NUMERIC, {123LU}}, /* .binaryEncodingId */
17304 sizeof(UA_EnumDefinition), /* .memSize */
17305 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17306 false, /* .pointerFree */
17307 false, /* .overlayable */
17308 1, /* .membersSize */
17309 EnumDefinition_members /* .members */
17310},
17311/* ReadEventDetails */
17312{
17313 UA_TYPENAME("ReadEventDetails") /* .typeName */
17314 {0, UA_NODEIDTYPE_NUMERIC, {644LU}}, /* .typeId */
17315 {0, UA_NODEIDTYPE_NUMERIC, {646LU}}, /* .binaryEncodingId */
17316 sizeof(UA_ReadEventDetails), /* .memSize */
17317 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17318 false, /* .pointerFree */
17319 false, /* .overlayable */
17320 4, /* .membersSize */
17321 ReadEventDetails_members /* .members */
17322},
17323/* ReadProcessedDetails */
17324{
17325 UA_TYPENAME("ReadProcessedDetails") /* .typeName */
17326 {0, UA_NODEIDTYPE_NUMERIC, {650LU}}, /* .typeId */
17327 {0, UA_NODEIDTYPE_NUMERIC, {652LU}}, /* .binaryEncodingId */
17328 sizeof(UA_ReadProcessedDetails), /* .memSize */
17329 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17330 false, /* .pointerFree */
17331 false, /* .overlayable */
17332 5, /* .membersSize */
17333 ReadProcessedDetails_members /* .members */
17334},
17335/* ModificationInfo */
17336{
17337 UA_TYPENAME("ModificationInfo") /* .typeName */
17338 {0, UA_NODEIDTYPE_NUMERIC, {11216LU}}, /* .typeId */
17339 {0, UA_NODEIDTYPE_NUMERIC, {11226LU}}, /* .binaryEncodingId */
17340 sizeof(UA_ModificationInfo), /* .memSize */
17341 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17342 false, /* .pointerFree */
17343 false, /* .overlayable */
17344 3, /* .membersSize */
17345 ModificationInfo_members /* .members */
17346},
17347/* HistoryModifiedData */
17348{
17349 UA_TYPENAME("HistoryModifiedData") /* .typeName */
17350 {0, UA_NODEIDTYPE_NUMERIC, {11217LU}}, /* .typeId */
17351 {0, UA_NODEIDTYPE_NUMERIC, {11227LU}}, /* .binaryEncodingId */
17352 sizeof(UA_HistoryModifiedData), /* .memSize */
17353 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17354 false, /* .pointerFree */
17355 false, /* .overlayable */
17356 2, /* .membersSize */
17357 HistoryModifiedData_members /* .members */
17358},
17359/* HistoryEvent */
17360{
17361 UA_TYPENAME("HistoryEvent") /* .typeName */
17362 {0, UA_NODEIDTYPE_NUMERIC, {659LU}}, /* .typeId */
17363 {0, UA_NODEIDTYPE_NUMERIC, {661LU}}, /* .binaryEncodingId */
17364 sizeof(UA_HistoryEvent), /* .memSize */
17365 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17366 false, /* .pointerFree */
17367 false, /* .overlayable */
17368 1, /* .membersSize */
17369 HistoryEvent_members /* .members */
17370},
17371/* DataChangeNotification */
17372{
17373 UA_TYPENAME("DataChangeNotification") /* .typeName */
17374 {0, UA_NODEIDTYPE_NUMERIC, {809LU}}, /* .typeId */
17375 {0, UA_NODEIDTYPE_NUMERIC, {811LU}}, /* .binaryEncodingId */
17376 sizeof(UA_DataChangeNotification), /* .memSize */
17377 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17378 false, /* .pointerFree */
17379 false, /* .overlayable */
17380 2, /* .membersSize */
17381 DataChangeNotification_members /* .members */
17382},
17383/* EventNotificationList */
17384{
17385 UA_TYPENAME("EventNotificationList") /* .typeName */
17386 {0, UA_NODEIDTYPE_NUMERIC, {914LU}}, /* .typeId */
17387 {0, UA_NODEIDTYPE_NUMERIC, {916LU}}, /* .binaryEncodingId */
17388 sizeof(UA_EventNotificationList), /* .memSize */
17389 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17390 false, /* .pointerFree */
17391 false, /* .overlayable */
17392 1, /* .membersSize */
17393 EventNotificationList_members /* .members */
17394},
17395};
17396
17397
17398/**** amalgamated original file "/build/src_generated/open62541/transport_generated.c" ****/
17399
17400/**********************************
17401 * Autogenerated -- do not modify *
17402 **********************************/
17403
17404
17405/* MessageType */
17406#define MessageType_members NULL
17407
17408/* ChunkType */
17409#define ChunkType_members NULL
17410
17411/* TcpMessageHeader */
17412static UA_DataTypeMember TcpMessageHeader_members[2] = {
17413{
17414 UA_TYPENAME("MessageTypeAndChunkType") /* .memberName */
17415 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17416 0, /* .padding */
17417 false, /* .isArray */
17418 false /* .isOptional */
17419},
17420{
17421 UA_TYPENAME("MessageSize") /* .memberName */
17422 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17423 offsetof(UA_TcpMessageHeader, messageSize) - offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) - sizeof(UA_UInt32), /* .padding */
17424 false, /* .isArray */
17425 false /* .isOptional */
17426},};
17427
17428/* TcpHelloMessage */
17429static UA_DataTypeMember TcpHelloMessage_members[6] = {
17430{
17431 UA_TYPENAME("ProtocolVersion") /* .memberName */
17432 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17433 0, /* .padding */
17434 false, /* .isArray */
17435 false /* .isOptional */
17436},
17437{
17438 UA_TYPENAME("ReceiveBufferSize") /* .memberName */
17439 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17440 offsetof(UA_TcpHelloMessage, receiveBufferSize) - offsetof(UA_TcpHelloMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */
17441 false, /* .isArray */
17442 false /* .isOptional */
17443},
17444{
17445 UA_TYPENAME("SendBufferSize") /* .memberName */
17446 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17447 offsetof(UA_TcpHelloMessage, sendBufferSize) - offsetof(UA_TcpHelloMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */
17448 false, /* .isArray */
17449 false /* .isOptional */
17450},
17451{
17452 UA_TYPENAME("MaxMessageSize") /* .memberName */
17453 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17454 offsetof(UA_TcpHelloMessage, maxMessageSize) - offsetof(UA_TcpHelloMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */
17455 false, /* .isArray */
17456 false /* .isOptional */
17457},
17458{
17459 UA_TYPENAME("MaxChunkCount") /* .memberName */
17460 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17461 offsetof(UA_TcpHelloMessage, maxChunkCount) - offsetof(UA_TcpHelloMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */
17462 false, /* .isArray */
17463 false /* .isOptional */
17464},
17465{
17466 UA_TYPENAME("EndpointUrl") /* .memberName */
17467 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
17468 offsetof(UA_TcpHelloMessage, endpointUrl) - offsetof(UA_TcpHelloMessage, maxChunkCount) - sizeof(UA_UInt32), /* .padding */
17469 false, /* .isArray */
17470 false /* .isOptional */
17471},};
17472
17473/* TcpAcknowledgeMessage */
17474static UA_DataTypeMember TcpAcknowledgeMessage_members[5] = {
17475{
17476 UA_TYPENAME("ProtocolVersion") /* .memberName */
17477 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17478 0, /* .padding */
17479 false, /* .isArray */
17480 false /* .isOptional */
17481},
17482{
17483 UA_TYPENAME("ReceiveBufferSize") /* .memberName */
17484 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17485 offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - offsetof(UA_TcpAcknowledgeMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */
17486 false, /* .isArray */
17487 false /* .isOptional */
17488},
17489{
17490 UA_TYPENAME("SendBufferSize") /* .memberName */
17491 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17492 offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */
17493 false, /* .isArray */
17494 false /* .isOptional */
17495},
17496{
17497 UA_TYPENAME("MaxMessageSize") /* .memberName */
17498 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17499 offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */
17500 false, /* .isArray */
17501 false /* .isOptional */
17502},
17503{
17504 UA_TYPENAME("MaxChunkCount") /* .memberName */
17505 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17506 offsetof(UA_TcpAcknowledgeMessage, maxChunkCount) - offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */
17507 false, /* .isArray */
17508 false /* .isOptional */
17509},};
17510
17511/* TcpErrorMessage */
17512static UA_DataTypeMember TcpErrorMessage_members[2] = {
17513{
17514 UA_TYPENAME("Error") /* .memberName */
17515 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17516 0, /* .padding */
17517 false, /* .isArray */
17518 false /* .isOptional */
17519},
17520{
17521 UA_TYPENAME("Reason") /* .memberName */
17522 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
17523 offsetof(UA_TcpErrorMessage, reason) - offsetof(UA_TcpErrorMessage, error) - sizeof(UA_UInt32), /* .padding */
17524 false, /* .isArray */
17525 false /* .isOptional */
17526},};
17527
17528/* AsymmetricAlgorithmSecurityHeader */
17529static UA_DataTypeMember AsymmetricAlgorithmSecurityHeader_members[3] = {
17530{
17531 UA_TYPENAME("SecurityPolicyUri") /* .memberName */
17532 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
17533 0, /* .padding */
17534 false, /* .isArray */
17535 false /* .isOptional */
17536},
17537{
17538 UA_TYPENAME("SenderCertificate") /* .memberName */
17539 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
17540 offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, securityPolicyUri) - sizeof(UA_ByteString), /* .padding */
17541 false, /* .isArray */
17542 false /* .isOptional */
17543},
17544{
17545 UA_TYPENAME("ReceiverCertificateThumbprint") /* .memberName */
17546 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
17547 offsetof(UA_AsymmetricAlgorithmSecurityHeader, receiverCertificateThumbprint) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - sizeof(UA_ByteString), /* .padding */
17548 false, /* .isArray */
17549 false /* .isOptional */
17550},};
17551
17552/* SequenceHeader */
17553static UA_DataTypeMember SequenceHeader_members[2] = {
17554{
17555 UA_TYPENAME("SequenceNumber") /* .memberName */
17556 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17557 0, /* .padding */
17558 false, /* .isArray */
17559 false /* .isOptional */
17560},
17561{
17562 UA_TYPENAME("RequestId") /* .memberName */
17563 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17564 offsetof(UA_SequenceHeader, requestId) - offsetof(UA_SequenceHeader, sequenceNumber) - sizeof(UA_UInt32), /* .padding */
17565 false, /* .isArray */
17566 false /* .isOptional */
17567},};
17568const UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT] = {
17569/* MessageType */
17570{
17571 UA_TYPENAME("MessageType") /* .typeName */
17572 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17573 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17574 sizeof(UA_MessageType), /* .memSize */
17575 UA_DATATYPEKIND_ENUM, /* .typeKind */
17576 true, /* .pointerFree */
17577 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17578 0, /* .membersSize */
17579 MessageType_members /* .members */
17580},
17581/* ChunkType */
17582{
17583 UA_TYPENAME("ChunkType") /* .typeName */
17584 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17585 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17586 sizeof(UA_ChunkType), /* .memSize */
17587 UA_DATATYPEKIND_ENUM, /* .typeKind */
17588 true, /* .pointerFree */
17589 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17590 0, /* .membersSize */
17591 ChunkType_members /* .members */
17592},
17593/* TcpMessageHeader */
17594{
17595 UA_TYPENAME("TcpMessageHeader") /* .typeName */
17596 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17597 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17598 sizeof(UA_TcpMessageHeader), /* .memSize */
17599 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17600 true, /* .pointerFree */
17601 false, /* .overlayable */
17602 2, /* .membersSize */
17603 TcpMessageHeader_members /* .members */
17604},
17605/* TcpHelloMessage */
17606{
17607 UA_TYPENAME("TcpHelloMessage") /* .typeName */
17608 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17609 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17610 sizeof(UA_TcpHelloMessage), /* .memSize */
17611 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17612 false, /* .pointerFree */
17613 false, /* .overlayable */
17614 6, /* .membersSize */
17615 TcpHelloMessage_members /* .members */
17616},
17617/* TcpAcknowledgeMessage */
17618{
17619 UA_TYPENAME("TcpAcknowledgeMessage") /* .typeName */
17620 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17621 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17622 sizeof(UA_TcpAcknowledgeMessage), /* .memSize */
17623 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17624 true, /* .pointerFree */
17625 false, /* .overlayable */
17626 5, /* .membersSize */
17627 TcpAcknowledgeMessage_members /* .members */
17628},
17629/* TcpErrorMessage */
17630{
17631 UA_TYPENAME("TcpErrorMessage") /* .typeName */
17632 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17633 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17634 sizeof(UA_TcpErrorMessage), /* .memSize */
17635 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17636 false, /* .pointerFree */
17637 false, /* .overlayable */
17638 2, /* .membersSize */
17639 TcpErrorMessage_members /* .members */
17640},
17641/* AsymmetricAlgorithmSecurityHeader */
17642{
17643 UA_TYPENAME("AsymmetricAlgorithmSecurityHeader") /* .typeName */
17644 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17645 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17646 sizeof(UA_AsymmetricAlgorithmSecurityHeader), /* .memSize */
17647 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17648 false, /* .pointerFree */
17649 false, /* .overlayable */
17650 3, /* .membersSize */
17651 AsymmetricAlgorithmSecurityHeader_members /* .members */
17652},
17653/* SequenceHeader */
17654{
17655 UA_TYPENAME("SequenceHeader") /* .typeName */
17656 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17657 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17658 sizeof(UA_SequenceHeader), /* .memSize */
17659 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17660 true, /* .pointerFree */
17661 false, /* .overlayable */
17662 2, /* .membersSize */
17663 SequenceHeader_members /* .members */
17664},
17665};
17666
17667
17668/**** amalgamated original file "/build/src_generated/open62541/statuscodes.c" ****/
17669
17670/**********************************
17671 * Autogenerated -- do not modify *
17672 **********************************/
17673
17674
17675typedef struct {
17676 UA_StatusCode code;
17677 const char *name;
17678} UA_StatusCodeName;
17679
17680#ifndef UA_ENABLE_STATUSCODE_DESCRIPTIONS
17681static const char * emptyStatusCodeName = "";
17682const char * UA_StatusCode_name(UA_StatusCode code) {
17683 return emptyStatusCodeName;
17684}
17685#else
17686static const size_t statusCodeDescriptionsSize = 252;
17687static const UA_StatusCodeName statusCodeDescriptions[252] = {
17688 {UA_STATUSCODE_GOOD, "Good"},
17689 {UA_STATUSCODE_GOOD, "Good"},
17690 {UA_STATUSCODE_UNCERTAIN, "Uncertain"},
17691 {UA_STATUSCODE_BAD, "Bad"},
17692 {UA_STATUSCODE_BADUNEXPECTEDERROR, "BadUnexpectedError"},
17693 {UA_STATUSCODE_BADINTERNALERROR, "BadInternalError"},
17694 {UA_STATUSCODE_BADOUTOFMEMORY, "BadOutOfMemory"},
17695 {UA_STATUSCODE_BADRESOURCEUNAVAILABLE, "BadResourceUnavailable"},
17696 {UA_STATUSCODE_BADCOMMUNICATIONERROR, "BadCommunicationError"},
17697 {UA_STATUSCODE_BADENCODINGERROR, "BadEncodingError"},
17698 {UA_STATUSCODE_BADDECODINGERROR, "BadDecodingError"},
17699 {UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED, "BadEncodingLimitsExceeded"},
17700 {UA_STATUSCODE_BADREQUESTTOOLARGE, "BadRequestTooLarge"},
17701 {UA_STATUSCODE_BADRESPONSETOOLARGE, "BadResponseTooLarge"},
17702 {UA_STATUSCODE_BADUNKNOWNRESPONSE, "BadUnknownResponse"},
17703 {UA_STATUSCODE_BADTIMEOUT, "BadTimeout"},
17704 {UA_STATUSCODE_BADSERVICEUNSUPPORTED, "BadServiceUnsupported"},
17705 {UA_STATUSCODE_BADSHUTDOWN, "BadShutdown"},
17706 {UA_STATUSCODE_BADSERVERNOTCONNECTED, "BadServerNotConnected"},
17707 {UA_STATUSCODE_BADSERVERHALTED, "BadServerHalted"},
17708 {UA_STATUSCODE_BADNOTHINGTODO, "BadNothingToDo"},
17709 {UA_STATUSCODE_BADTOOMANYOPERATIONS, "BadTooManyOperations"},
17710 {UA_STATUSCODE_BADTOOMANYMONITOREDITEMS, "BadTooManyMonitoredItems"},
17711 {UA_STATUSCODE_BADDATATYPEIDUNKNOWN, "BadDataTypeIdUnknown"},
17712 {UA_STATUSCODE_BADCERTIFICATEINVALID, "BadCertificateInvalid"},
17713 {UA_STATUSCODE_BADSECURITYCHECKSFAILED, "BadSecurityChecksFailed"},
17714 {UA_STATUSCODE_BADCERTIFICATEPOLICYCHECKFAILED, "BadCertificatePolicyCheckFailed"},
17715 {UA_STATUSCODE_BADCERTIFICATETIMEINVALID, "BadCertificateTimeInvalid"},
17716 {UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID, "BadCertificateIssuerTimeInvalid"},
17717 {UA_STATUSCODE_BADCERTIFICATEHOSTNAMEINVALID, "BadCertificateHostNameInvalid"},
17718 {UA_STATUSCODE_BADCERTIFICATEURIINVALID, "BadCertificateUriInvalid"},
17719 {UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED, "BadCertificateUseNotAllowed"},
17720 {UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED, "BadCertificateIssuerUseNotAllowed"},
17721 {UA_STATUSCODE_BADCERTIFICATEUNTRUSTED, "BadCertificateUntrusted"},
17722 {UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN, "BadCertificateRevocationUnknown"},
17723 {UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN, "BadCertificateIssuerRevocationUnknown"},
17724 {UA_STATUSCODE_BADCERTIFICATEREVOKED, "BadCertificateRevoked"},
17725 {UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED, "BadCertificateIssuerRevoked"},
17726 {UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE, "BadCertificateChainIncomplete"},
17727 {UA_STATUSCODE_BADUSERACCESSDENIED, "BadUserAccessDenied"},
17728 {UA_STATUSCODE_BADIDENTITYTOKENINVALID, "BadIdentityTokenInvalid"},
17729 {UA_STATUSCODE_BADIDENTITYTOKENREJECTED, "BadIdentityTokenRejected"},
17730 {UA_STATUSCODE_BADSECURECHANNELIDINVALID, "BadSecureChannelIdInvalid"},
17731 {UA_STATUSCODE_BADINVALIDTIMESTAMP, "BadInvalidTimestamp"},
17732 {UA_STATUSCODE_BADNONCEINVALID, "BadNonceInvalid"},
17733 {UA_STATUSCODE_BADSESSIONIDINVALID, "BadSessionIdInvalid"},
17734 {UA_STATUSCODE_BADSESSIONCLOSED, "BadSessionClosed"},
17735 {UA_STATUSCODE_BADSESSIONNOTACTIVATED, "BadSessionNotActivated"},
17736 {UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID, "BadSubscriptionIdInvalid"},
17737 {UA_STATUSCODE_BADREQUESTHEADERINVALID, "BadRequestHeaderInvalid"},
17738 {UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID, "BadTimestampsToReturnInvalid"},
17739 {UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT, "BadRequestCancelledByClient"},
17740 {UA_STATUSCODE_BADTOOMANYARGUMENTS, "BadTooManyArguments"},
17741 {UA_STATUSCODE_BADLICENSEEXPIRED, "BadLicenseExpired"},
17742 {UA_STATUSCODE_BADLICENSELIMITSEXCEEDED, "BadLicenseLimitsExceeded"},
17743 {UA_STATUSCODE_BADLICENSENOTAVAILABLE, "BadLicenseNotAvailable"},
17744 {UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED, "GoodSubscriptionTransferred"},
17745 {UA_STATUSCODE_GOODCOMPLETESASYNCHRONOUSLY, "GoodCompletesAsynchronously"},
17746 {UA_STATUSCODE_GOODOVERLOAD, "GoodOverload"},
17747 {UA_STATUSCODE_GOODCLAMPED, "GoodClamped"},
17748 {UA_STATUSCODE_BADNOCOMMUNICATION, "BadNoCommunication"},
17749 {UA_STATUSCODE_BADWAITINGFORINITIALDATA, "BadWaitingForInitialData"},
17750 {UA_STATUSCODE_BADNODEIDINVALID, "BadNodeIdInvalid"},
17751 {UA_STATUSCODE_BADNODEIDUNKNOWN, "BadNodeIdUnknown"},
17752 {UA_STATUSCODE_BADATTRIBUTEIDINVALID, "BadAttributeIdInvalid"},
17753 {UA_STATUSCODE_BADINDEXRANGEINVALID, "BadIndexRangeInvalid"},
17754 {UA_STATUSCODE_BADINDEXRANGENODATA, "BadIndexRangeNoData"},
17755 {UA_STATUSCODE_BADDATAENCODINGINVALID, "BadDataEncodingInvalid"},
17756 {UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED, "BadDataEncodingUnsupported"},
17757 {UA_STATUSCODE_BADNOTREADABLE, "BadNotReadable"},
17758 {UA_STATUSCODE_BADNOTWRITABLE, "BadNotWritable"},
17759 {UA_STATUSCODE_BADOUTOFRANGE, "BadOutOfRange"},
17760 {UA_STATUSCODE_BADNOTSUPPORTED, "BadNotSupported"},
17761 {UA_STATUSCODE_BADNOTFOUND, "BadNotFound"},
17762 {UA_STATUSCODE_BADOBJECTDELETED, "BadObjectDeleted"},
17763 {UA_STATUSCODE_BADNOTIMPLEMENTED, "BadNotImplemented"},
17764 {UA_STATUSCODE_BADMONITORINGMODEINVALID, "BadMonitoringModeInvalid"},
17765 {UA_STATUSCODE_BADMONITOREDITEMIDINVALID, "BadMonitoredItemIdInvalid"},
17766 {UA_STATUSCODE_BADMONITOREDITEMFILTERINVALID, "BadMonitoredItemFilterInvalid"},
17767 {UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED, "BadMonitoredItemFilterUnsupported"},
17768 {UA_STATUSCODE_BADFILTERNOTALLOWED, "BadFilterNotAllowed"},
17769 {UA_STATUSCODE_BADSTRUCTUREMISSING, "BadStructureMissing"},
17770 {UA_STATUSCODE_BADEVENTFILTERINVALID, "BadEventFilterInvalid"},
17771 {UA_STATUSCODE_BADCONTENTFILTERINVALID, "BadContentFilterInvalid"},
17772 {UA_STATUSCODE_BADFILTEROPERATORINVALID, "BadFilterOperatorInvalid"},
17773 {UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED, "BadFilterOperatorUnsupported"},
17774 {UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH, "BadFilterOperandCountMismatch"},
17775 {UA_STATUSCODE_BADFILTEROPERANDINVALID, "BadFilterOperandInvalid"},
17776 {UA_STATUSCODE_BADFILTERELEMENTINVALID, "BadFilterElementInvalid"},
17777 {UA_STATUSCODE_BADFILTERLITERALINVALID, "BadFilterLiteralInvalid"},
17778 {UA_STATUSCODE_BADCONTINUATIONPOINTINVALID, "BadContinuationPointInvalid"},
17779 {UA_STATUSCODE_BADNOCONTINUATIONPOINTS, "BadNoContinuationPoints"},
17780 {UA_STATUSCODE_BADREFERENCETYPEIDINVALID, "BadReferenceTypeIdInvalid"},
17781 {UA_STATUSCODE_BADBROWSEDIRECTIONINVALID, "BadBrowseDirectionInvalid"},
17782 {UA_STATUSCODE_BADNODENOTINVIEW, "BadNodeNotInView"},
17783 {UA_STATUSCODE_BADNUMERICOVERFLOW, "BadNumericOverflow"},
17784 {UA_STATUSCODE_BADSERVERURIINVALID, "BadServerUriInvalid"},
17785 {UA_STATUSCODE_BADSERVERNAMEMISSING, "BadServerNameMissing"},
17786 {UA_STATUSCODE_BADDISCOVERYURLMISSING, "BadDiscoveryUrlMissing"},
17787 {UA_STATUSCODE_BADSEMPAHOREFILEMISSING, "BadSempahoreFileMissing"},
17788 {UA_STATUSCODE_BADREQUESTTYPEINVALID, "BadRequestTypeInvalid"},
17789 {UA_STATUSCODE_BADSECURITYMODEREJECTED, "BadSecurityModeRejected"},
17790 {UA_STATUSCODE_BADSECURITYPOLICYREJECTED, "BadSecurityPolicyRejected"},
17791 {UA_STATUSCODE_BADTOOMANYSESSIONS, "BadTooManySessions"},
17792 {UA_STATUSCODE_BADUSERSIGNATUREINVALID, "BadUserSignatureInvalid"},
17793 {UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID, "BadApplicationSignatureInvalid"},
17794 {UA_STATUSCODE_BADNOVALIDCERTIFICATES, "BadNoValidCertificates"},
17795 {UA_STATUSCODE_BADIDENTITYCHANGENOTSUPPORTED, "BadIdentityChangeNotSupported"},
17796 {UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST, "BadRequestCancelledByRequest"},
17797 {UA_STATUSCODE_BADPARENTNODEIDINVALID, "BadParentNodeIdInvalid"},
17798 {UA_STATUSCODE_BADREFERENCENOTALLOWED, "BadReferenceNotAllowed"},
17799 {UA_STATUSCODE_BADNODEIDREJECTED, "BadNodeIdRejected"},
17800 {UA_STATUSCODE_BADNODEIDEXISTS, "BadNodeIdExists"},
17801 {UA_STATUSCODE_BADNODECLASSINVALID, "BadNodeClassInvalid"},
17802 {UA_STATUSCODE_BADBROWSENAMEINVALID, "BadBrowseNameInvalid"},
17803 {UA_STATUSCODE_BADBROWSENAMEDUPLICATED, "BadBrowseNameDuplicated"},
17804 {UA_STATUSCODE_BADNODEATTRIBUTESINVALID, "BadNodeAttributesInvalid"},
17805 {UA_STATUSCODE_BADTYPEDEFINITIONINVALID, "BadTypeDefinitionInvalid"},
17806 {UA_STATUSCODE_BADSOURCENODEIDINVALID, "BadSourceNodeIdInvalid"},
17807 {UA_STATUSCODE_BADTARGETNODEIDINVALID, "BadTargetNodeIdInvalid"},
17808 {UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED, "BadDuplicateReferenceNotAllowed"},
17809 {UA_STATUSCODE_BADINVALIDSELFREFERENCE, "BadInvalidSelfReference"},
17810 {UA_STATUSCODE_BADREFERENCELOCALONLY, "BadReferenceLocalOnly"},
17811 {UA_STATUSCODE_BADNODELETERIGHTS, "BadNoDeleteRights"},
17812 {UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED, "UncertainReferenceNotDeleted"},
17813 {UA_STATUSCODE_BADSERVERINDEXINVALID, "BadServerIndexInvalid"},
17814 {UA_STATUSCODE_BADVIEWIDUNKNOWN, "BadViewIdUnknown"},
17815 {UA_STATUSCODE_BADVIEWTIMESTAMPINVALID, "BadViewTimestampInvalid"},
17816 {UA_STATUSCODE_BADVIEWPARAMETERMISMATCH, "BadViewParameterMismatch"},
17817 {UA_STATUSCODE_BADVIEWVERSIONINVALID, "BadViewVersionInvalid"},
17818 {UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE, "UncertainNotAllNodesAvailable"},
17819 {UA_STATUSCODE_GOODRESULTSMAYBEINCOMPLETE, "GoodResultsMayBeIncomplete"},
17820 {UA_STATUSCODE_BADNOTTYPEDEFINITION, "BadNotTypeDefinition"},
17821 {UA_STATUSCODE_UNCERTAINREFERENCEOUTOFSERVER, "UncertainReferenceOutOfServer"},
17822 {UA_STATUSCODE_BADTOOMANYMATCHES, "BadTooManyMatches"},
17823 {UA_STATUSCODE_BADQUERYTOOCOMPLEX, "BadQueryTooComplex"},
17824 {UA_STATUSCODE_BADNOMATCH, "BadNoMatch"},
17825 {UA_STATUSCODE_BADMAXAGEINVALID, "BadMaxAgeInvalid"},
17826 {UA_STATUSCODE_BADSECURITYMODEINSUFFICIENT, "BadSecurityModeInsufficient"},
17827 {UA_STATUSCODE_BADHISTORYOPERATIONINVALID, "BadHistoryOperationInvalid"},
17828 {UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED, "BadHistoryOperationUnsupported"},
17829 {UA_STATUSCODE_BADINVALIDTIMESTAMPARGUMENT, "BadInvalidTimestampArgument"},
17830 {UA_STATUSCODE_BADWRITENOTSUPPORTED, "BadWriteNotSupported"},
17831 {UA_STATUSCODE_BADTYPEMISMATCH, "BadTypeMismatch"},
17832 {UA_STATUSCODE_BADMETHODINVALID, "BadMethodInvalid"},
17833 {UA_STATUSCODE_BADARGUMENTSMISSING, "BadArgumentsMissing"},
17834 {UA_STATUSCODE_BADNOTEXECUTABLE, "BadNotExecutable"},
17835 {UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS, "BadTooManySubscriptions"},
17836 {UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS, "BadTooManyPublishRequests"},
17837 {UA_STATUSCODE_BADNOSUBSCRIPTION, "BadNoSubscription"},
17838 {UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN, "BadSequenceNumberUnknown"},
17839 {UA_STATUSCODE_GOODRETRANSMISSIONQUEUENOTSUPPORTED, "GoodRetransmissionQueueNotSupported"},
17840 {UA_STATUSCODE_BADMESSAGENOTAVAILABLE, "BadMessageNotAvailable"},
17841 {UA_STATUSCODE_BADINSUFFICIENTCLIENTPROFILE, "BadInsufficientClientProfile"},
17842 {UA_STATUSCODE_BADSTATENOTACTIVE, "BadStateNotActive"},
17843 {UA_STATUSCODE_BADALREADYEXISTS, "BadAlreadyExists"},
17844 {UA_STATUSCODE_BADTCPSERVERTOOBUSY, "BadTcpServerTooBusy"},
17845 {UA_STATUSCODE_BADTCPMESSAGETYPEINVALID, "BadTcpMessageTypeInvalid"},
17846 {UA_STATUSCODE_BADTCPSECURECHANNELUNKNOWN, "BadTcpSecureChannelUnknown"},
17847 {UA_STATUSCODE_BADTCPMESSAGETOOLARGE, "BadTcpMessageTooLarge"},
17848 {UA_STATUSCODE_BADTCPNOTENOUGHRESOURCES, "BadTcpNotEnoughResources"},
17849 {UA_STATUSCODE_BADTCPINTERNALERROR, "BadTcpInternalError"},
17850 {UA_STATUSCODE_BADTCPENDPOINTURLINVALID, "BadTcpEndpointUrlInvalid"},
17851 {UA_STATUSCODE_BADREQUESTINTERRUPTED, "BadRequestInterrupted"},
17852 {UA_STATUSCODE_BADREQUESTTIMEOUT, "BadRequestTimeout"},
17853 {UA_STATUSCODE_BADSECURECHANNELCLOSED, "BadSecureChannelClosed"},
17854 {UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN, "BadSecureChannelTokenUnknown"},
17855 {UA_STATUSCODE_BADSEQUENCENUMBERINVALID, "BadSequenceNumberInvalid"},
17856 {UA_STATUSCODE_BADPROTOCOLVERSIONUNSUPPORTED, "BadProtocolVersionUnsupported"},
17857 {UA_STATUSCODE_BADCONFIGURATIONERROR, "BadConfigurationError"},
17858 {UA_STATUSCODE_BADNOTCONNECTED, "BadNotConnected"},
17859 {UA_STATUSCODE_BADDEVICEFAILURE, "BadDeviceFailure"},
17860 {UA_STATUSCODE_BADSENSORFAILURE, "BadSensorFailure"},
17861 {UA_STATUSCODE_BADOUTOFSERVICE, "BadOutOfService"},
17862 {UA_STATUSCODE_BADDEADBANDFILTERINVALID, "BadDeadbandFilterInvalid"},
17863 {UA_STATUSCODE_UNCERTAINNOCOMMUNICATIONLASTUSABLEVALUE, "UncertainNoCommunicationLastUsableValue"},
17864 {UA_STATUSCODE_UNCERTAINLASTUSABLEVALUE, "UncertainLastUsableValue"},
17865 {UA_STATUSCODE_UNCERTAINSUBSTITUTEVALUE, "UncertainSubstituteValue"},
17866 {UA_STATUSCODE_UNCERTAININITIALVALUE, "UncertainInitialValue"},
17867 {UA_STATUSCODE_UNCERTAINSENSORNOTACCURATE, "UncertainSensorNotAccurate"},
17868 {UA_STATUSCODE_UNCERTAINENGINEERINGUNITSEXCEEDED, "UncertainEngineeringUnitsExceeded"},
17869 {UA_STATUSCODE_UNCERTAINSUBNORMAL, "UncertainSubNormal"},
17870 {UA_STATUSCODE_GOODLOCALOVERRIDE, "GoodLocalOverride"},
17871 {UA_STATUSCODE_BADREFRESHINPROGRESS, "BadRefreshInProgress"},
17872 {UA_STATUSCODE_BADCONDITIONALREADYDISABLED, "BadConditionAlreadyDisabled"},
17873 {UA_STATUSCODE_BADCONDITIONALREADYENABLED, "BadConditionAlreadyEnabled"},
17874 {UA_STATUSCODE_BADCONDITIONDISABLED, "BadConditionDisabled"},
17875 {UA_STATUSCODE_BADEVENTIDUNKNOWN, "BadEventIdUnknown"},
17876 {UA_STATUSCODE_BADEVENTNOTACKNOWLEDGEABLE, "BadEventNotAcknowledgeable"},
17877 {UA_STATUSCODE_BADDIALOGNOTACTIVE, "BadDialogNotActive"},
17878 {UA_STATUSCODE_BADDIALOGRESPONSEINVALID, "BadDialogResponseInvalid"},
17879 {UA_STATUSCODE_BADCONDITIONBRANCHALREADYACKED, "BadConditionBranchAlreadyAcked"},
17880 {UA_STATUSCODE_BADCONDITIONBRANCHALREADYCONFIRMED, "BadConditionBranchAlreadyConfirmed"},
17881 {UA_STATUSCODE_BADCONDITIONALREADYSHELVED, "BadConditionAlreadyShelved"},
17882 {UA_STATUSCODE_BADCONDITIONNOTSHELVED, "BadConditionNotShelved"},
17883 {UA_STATUSCODE_BADSHELVINGTIMEOUTOFRANGE, "BadShelvingTimeOutOfRange"},
17884 {UA_STATUSCODE_BADNODATA, "BadNoData"},
17885 {UA_STATUSCODE_BADBOUNDNOTFOUND, "BadBoundNotFound"},
17886 {UA_STATUSCODE_BADBOUNDNOTSUPPORTED, "BadBoundNotSupported"},
17887 {UA_STATUSCODE_BADDATALOST, "BadDataLost"},
17888 {UA_STATUSCODE_BADDATAUNAVAILABLE, "BadDataUnavailable"},
17889 {UA_STATUSCODE_BADENTRYEXISTS, "BadEntryExists"},
17890 {UA_STATUSCODE_BADNOENTRYEXISTS, "BadNoEntryExists"},
17891 {UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED, "BadTimestampNotSupported"},
17892 {UA_STATUSCODE_GOODENTRYINSERTED, "GoodEntryInserted"},
17893 {UA_STATUSCODE_GOODENTRYREPLACED, "GoodEntryReplaced"},
17894 {UA_STATUSCODE_UNCERTAINDATASUBNORMAL, "UncertainDataSubNormal"},
17895 {UA_STATUSCODE_GOODNODATA, "GoodNoData"},
17896 {UA_STATUSCODE_GOODMOREDATA, "GoodMoreData"},
17897 {UA_STATUSCODE_BADAGGREGATELISTMISMATCH, "BadAggregateListMismatch"},
17898 {UA_STATUSCODE_BADAGGREGATENOTSUPPORTED, "BadAggregateNotSupported"},
17899 {UA_STATUSCODE_BADAGGREGATEINVALIDINPUTS, "BadAggregateInvalidInputs"},
17900 {UA_STATUSCODE_BADAGGREGATECONFIGURATIONREJECTED, "BadAggregateConfigurationRejected"},
17901 {UA_STATUSCODE_GOODDATAIGNORED, "GoodDataIgnored"},
17902 {UA_STATUSCODE_BADREQUESTNOTALLOWED, "BadRequestNotAllowed"},
17903 {UA_STATUSCODE_BADREQUESTNOTCOMPLETE, "BadRequestNotComplete"},
17904 {UA_STATUSCODE_BADTICKETREQUIRED, "BadTicketRequired"},
17905 {UA_STATUSCODE_BADTICKETINVALID, "BadTicketInvalid"},
17906 {UA_STATUSCODE_GOODEDITED, "GoodEdited"},
17907 {UA_STATUSCODE_GOODPOSTACTIONFAILED, "GoodPostActionFailed"},
17908 {UA_STATUSCODE_UNCERTAINDOMINANTVALUECHANGED, "UncertainDominantValueChanged"},
17909 {UA_STATUSCODE_GOODDEPENDENTVALUECHANGED, "GoodDependentValueChanged"},
17910 {UA_STATUSCODE_BADDOMINANTVALUECHANGED, "BadDominantValueChanged"},
17911 {UA_STATUSCODE_UNCERTAINDEPENDENTVALUECHANGED, "UncertainDependentValueChanged"},
17912 {UA_STATUSCODE_BADDEPENDENTVALUECHANGED, "BadDependentValueChanged"},
17913 {UA_STATUSCODE_GOODEDITED_DEPENDENTVALUECHANGED, "GoodEdited_DependentValueChanged"},
17914 {UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED, "GoodEdited_DominantValueChanged"},
17915 {UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "GoodEdited_DominantValueChanged_DependentValueChanged"},
17916 {UA_STATUSCODE_BADEDITED_OUTOFRANGE, "BadEdited_OutOfRange"},
17917 {UA_STATUSCODE_BADINITIALVALUE_OUTOFRANGE, "BadInitialValue_OutOfRange"},
17918 {UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED, "BadOutOfRange_DominantValueChanged"},
17919 {UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED, "BadEdited_OutOfRange_DominantValueChanged"},
17920 {UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "BadOutOfRange_DominantValueChanged_DependentValueChanged"},
17921 {UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "BadEdited_OutOfRange_DominantValueChanged_DependentValueChanged"},
17922 {UA_STATUSCODE_GOODCOMMUNICATIONEVENT, "GoodCommunicationEvent"},
17923 {UA_STATUSCODE_GOODSHUTDOWNEVENT, "GoodShutdownEvent"},
17924 {UA_STATUSCODE_GOODCALLAGAIN, "GoodCallAgain"},
17925 {UA_STATUSCODE_GOODNONCRITICALTIMEOUT, "GoodNonCriticalTimeout"},
17926 {UA_STATUSCODE_BADINVALIDARGUMENT, "BadInvalidArgument"},
17927 {UA_STATUSCODE_BADCONNECTIONREJECTED, "BadConnectionRejected"},
17928 {UA_STATUSCODE_BADDISCONNECT, "BadDisconnect"},
17929 {UA_STATUSCODE_BADCONNECTIONCLOSED, "BadConnectionClosed"},
17930 {UA_STATUSCODE_BADINVALIDSTATE, "BadInvalidState"},
17931 {UA_STATUSCODE_BADENDOFSTREAM, "BadEndOfStream"},
17932 {UA_STATUSCODE_BADNODATAAVAILABLE, "BadNoDataAvailable"},
17933 {UA_STATUSCODE_BADWAITINGFORRESPONSE, "BadWaitingForResponse"},
17934 {UA_STATUSCODE_BADOPERATIONABANDONED, "BadOperationAbandoned"},
17935 {UA_STATUSCODE_BADEXPECTEDSTREAMTOBLOCK, "BadExpectedStreamToBlock"},
17936 {UA_STATUSCODE_BADWOULDBLOCK, "BadWouldBlock"},
17937 {UA_STATUSCODE_BADSYNTAXERROR, "BadSyntaxError"},
17938 {UA_STATUSCODE_BADMAXCONNECTIONSREACHED, "BadMaxConnectionsReached"},
17939 {0xffffffff, "Unknown StatusCode"}
17940};
17941
17942const char * UA_StatusCode_name(UA_StatusCode code) {
17943 for (size_t i = 0; i < statusCodeDescriptionsSize; ++i) {
17944 if (UA_StatusCode_isEqualTop(s1: statusCodeDescriptions[i].code,s2: code))
17945 return statusCodeDescriptions[i].name;
17946 }
17947 return statusCodeDescriptions[statusCodeDescriptionsSize-1].name;
17948}
17949
17950#endif
17951
17952/**** amalgamated original file "/src/ua_util.c" ****/
17953
17954/* This Source Code Form is subject to the terms of the Mozilla Public
17955 * License, v. 2.0. If a copy of the MPL was not distributed with this
17956 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
17957 *
17958 * Copyright 2014, 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
17959 * Copyright 2014 (c) Florian Palm
17960 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
17961 */
17962
17963
17964
17965size_t
17966UA_readNumberWithBase(const UA_Byte *buf, size_t buflen, UA_UInt32 *number, UA_Byte base) {
17967 UA_assert(buf);
17968 UA_assert(number);
17969 u32 n = 0;
17970 size_t progress = 0;
17971 /* read numbers until the end or a non-number character appears */
17972 while(progress < buflen) {
17973 u8 c = buf[progress];
17974 if(c >= '0' && c <= '9' && c <= '0' + (base-1))
17975 n = (n * base) + c - '0';
17976 else if(base > 9 && c >= 'a' && c <= 'z' && c <= 'a' + (base-11))
17977 n = (n * base) + c-'a' + 10;
17978 else if(base > 9 && c >= 'A' && c <= 'Z' && c <= 'A' + (base-11))
17979 n = (n * base) + c-'A' + 10;
17980 else
17981 break;
17982 ++progress;
17983 }
17984 *number = n;
17985 return progress;
17986}
17987
17988size_t
17989UA_readNumber(const UA_Byte *buf, size_t buflen, UA_UInt32 *number) {
17990 return UA_readNumberWithBase(buf, buflen, number, base: 10);
17991}
17992
17993UA_StatusCode
17994UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
17995 u16 *outPort, UA_String *outPath) {
17996 UA_Boolean ipv6 = false;
17997
17998 /* Url must begin with "opc.tcp://" or opc.udp:// (if pubsub enabled) */
17999 if(endpointUrl->length < 11) {
18000 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18001 }
18002 if (strncmp(s1: (char*)endpointUrl->data, s2: "opc.tcp://", n: 10) != 0) {
18003#ifdef UA_ENABLE_PUBSUB
18004 if (strncmp((char*)endpointUrl->data, "opc.udp://", 10) != 0 &&
18005 strncmp((char*)endpointUrl->data, "opc.mqtt://", 11) != 0) {
18006 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18007 }
18008#else
18009 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18010#endif
18011 }
18012
18013 /* Where does the hostname end? */
18014 size_t curr = 10;
18015 if(endpointUrl->data[curr] == '[') {
18016 /* IPv6: opc.tcp://[2001:0db8:85a3::8a2e:0370:7334]:1234/path */
18017 for(; curr < endpointUrl->length; ++curr) {
18018 if(endpointUrl->data[curr] == ']')
18019 break;
18020 }
18021 if(curr == endpointUrl->length)
18022 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18023 curr++;
18024 ipv6 = true;
18025 } else {
18026 /* IPv4 or hostname: opc.tcp://something.something:1234/path */
18027 for(; curr < endpointUrl->length; ++curr) {
18028 if(endpointUrl->data[curr] == ':' || endpointUrl->data[curr] == '/')
18029 break;
18030 }
18031 }
18032
18033 /* Set the hostname */
18034 if(ipv6) {
18035 /* Skip the ipv6 '[]' container for getaddrinfo() later */
18036 outHostname->data = &endpointUrl->data[11];
18037 outHostname->length = curr - 12;
18038 } else {
18039 outHostname->data = &endpointUrl->data[10];
18040 outHostname->length = curr - 10;
18041 }
18042
18043 /* Empty string? */
18044 if(outHostname->length == 0)
18045 outHostname->data = NULL;
18046
18047 if(curr == endpointUrl->length)
18048 return UA_STATUSCODE_GOOD;
18049
18050 /* Set the port */
18051 if(endpointUrl->data[curr] == ':') {
18052 if(++curr == endpointUrl->length)
18053 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18054 u32 largeNum;
18055 size_t progress = UA_readNumber(buf: &endpointUrl->data[curr],
18056 buflen: endpointUrl->length - curr, number: &largeNum);
18057 if(progress == 0 || largeNum > 65535)
18058 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18059 /* Test if the end of a valid port was reached */
18060 curr += progress;
18061 if(curr == endpointUrl->length || endpointUrl->data[curr] == '/')
18062 *outPort = (u16)largeNum;
18063 if(curr == endpointUrl->length)
18064 return UA_STATUSCODE_GOOD;
18065 }
18066
18067 /* Set the path */
18068 UA_assert(curr < endpointUrl->length);
18069 if(endpointUrl->data[curr] != '/')
18070 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18071 if(++curr == endpointUrl->length)
18072 return UA_STATUSCODE_GOOD;
18073 outPath->data = &endpointUrl->data[curr];
18074 outPath->length = endpointUrl->length - curr;
18075
18076 /* Remove trailing slash from the path */
18077 if(endpointUrl->data[endpointUrl->length - 1] == '/')
18078 outPath->length--;
18079
18080 /* Empty string? */
18081 if(outPath->length == 0)
18082 outPath->data = NULL;
18083
18084 return UA_STATUSCODE_GOOD;
18085}
18086
18087UA_StatusCode
18088UA_parseEndpointUrlEthernet(const UA_String *endpointUrl, UA_String *target,
18089 UA_UInt16 *vid, UA_Byte *pcp) {
18090 /* Url must begin with "opc.eth://" */
18091 if(endpointUrl->length < 11) {
18092 return UA_STATUSCODE_BADINTERNALERROR;
18093 }
18094 if(strncmp(s1: (char*) endpointUrl->data, s2: "opc.eth://", n: 10) != 0) {
18095 return UA_STATUSCODE_BADINTERNALERROR;
18096 }
18097
18098 /* Where does the host address end? */
18099 size_t curr = 10;
18100 for(; curr < endpointUrl->length; ++curr) {
18101 if(endpointUrl->data[curr] == ':') {
18102 break;
18103 }
18104 }
18105
18106 /* set host address */
18107 target->data = &endpointUrl->data[10];
18108 target->length = curr - 10;
18109 if(curr == endpointUrl->length) {
18110 return UA_STATUSCODE_GOOD;
18111 }
18112
18113 /* Set VLAN */
18114 u32 value = 0;
18115 curr++; /* skip ':' */
18116 size_t progress = UA_readNumber(buf: &endpointUrl->data[curr],
18117 buflen: endpointUrl->length - curr, number: &value);
18118 if(progress == 0 || value > 4096) {
18119 return UA_STATUSCODE_BADINTERNALERROR;
18120 }
18121 curr += progress;
18122 if(curr == endpointUrl->length || endpointUrl->data[curr] == '.') {
18123 *vid = (UA_UInt16) value;
18124 }
18125 if(curr == endpointUrl->length) {
18126 return UA_STATUSCODE_GOOD;
18127 }
18128
18129 /* Set priority */
18130 if(endpointUrl->data[curr] != '.') {
18131 return UA_STATUSCODE_BADINTERNALERROR;
18132 }
18133 curr++; /* skip '.' */
18134 progress = UA_readNumber(buf: &endpointUrl->data[curr],
18135 buflen: endpointUrl->length - curr, number: &value);
18136 if(progress == 0 || value > 7) {
18137 return UA_STATUSCODE_BADINTERNALERROR;
18138 }
18139 curr += progress;
18140 if(curr != endpointUrl->length) {
18141 return UA_STATUSCODE_BADINTERNALERROR;
18142 }
18143 *pcp = (UA_Byte) value;
18144
18145 return UA_STATUSCODE_GOOD;
18146}
18147
18148UA_StatusCode
18149UA_ByteString_toBase64(const UA_ByteString *byteString,
18150 UA_String *str) {
18151 UA_String_init(p: str);
18152 if(!byteString || !byteString->data)
18153 return UA_STATUSCODE_GOOD;
18154
18155 str->data = (UA_Byte*)
18156 UA_base64(src: byteString->data, len: byteString->length, out_len: &str->length);
18157 if(!str->data)
18158 return UA_STATUSCODE_BADOUTOFMEMORY;
18159
18160 return UA_STATUSCODE_GOOD;
18161}
18162
18163UA_StatusCode UA_EXPORT
18164UA_ByteString_fromBase64(UA_ByteString *bs,
18165 const UA_String *input) {
18166 UA_ByteString_init(p: bs);
18167 if(input->length == 0)
18168 return UA_STATUSCODE_GOOD;
18169 bs->data = UA_unbase64(src: (const unsigned char*)input->data,
18170 len: input->length, out_len: &bs->length);
18171 /* TODO: Differentiate between encoding and memory errors */
18172 if(!bs->data)
18173 return UA_STATUSCODE_BADINTERNALERROR;
18174 return UA_STATUSCODE_GOOD;
18175}
18176
18177/* Key Value Map */
18178
18179UA_StatusCode
18180UA_KeyValueMap_setQualified(UA_KeyValuePair **map, size_t *mapSize,
18181 const UA_QualifiedName *key,
18182 const UA_Variant *value) {
18183 /* Parameter exists already */
18184 const UA_Variant *v = UA_KeyValueMap_getQualified(map: *map, mapSize: *mapSize, key);
18185 if(v) {
18186 UA_Variant copyV;
18187 UA_StatusCode res = UA_Variant_copy(src: v, dst: &copyV);
18188 if(res != UA_STATUSCODE_GOOD)
18189 return res;
18190 UA_Variant *target = (UA_Variant*)(uintptr_t)v;
18191 UA_Variant_clear(p: target);
18192 *target = copyV;
18193 return UA_STATUSCODE_GOOD;
18194 }
18195
18196 /* Append to the array */
18197 UA_KeyValuePair pair;
18198 pair.key = *key;
18199 pair.value = *value;
18200 return UA_Array_appendCopy(p: (void**)map, size: mapSize, newElem: &pair,
18201 type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
18202}
18203
18204UA_StatusCode
18205UA_KeyValueMap_set(UA_KeyValuePair **map, size_t *mapSize,
18206 const char *key, const UA_Variant *value) {
18207 UA_QualifiedName qnKey;
18208 qnKey.namespaceIndex = 0;
18209 qnKey.name = UA_STRING(chars: (char*)(uintptr_t)key);
18210 return UA_KeyValueMap_setQualified(map, mapSize, key: &qnKey, value);
18211}
18212
18213const UA_Variant *
18214UA_KeyValueMap_getQualified(UA_KeyValuePair *map, size_t mapSize,
18215 const UA_QualifiedName *key) {
18216 for(size_t i = 0; i < mapSize; i++) {
18217 if(map[i].key.namespaceIndex == key->namespaceIndex &&
18218 UA_String_equal(s1: &map[i].key.name, s2: &key->name))
18219 return &map[i].value;
18220
18221 }
18222 return NULL;
18223}
18224
18225const UA_Variant *
18226UA_KeyValueMap_get(UA_KeyValuePair *map, size_t mapSize,
18227 const char *key) {
18228 UA_QualifiedName qnKey;
18229 qnKey.namespaceIndex = 0;
18230 qnKey.name = UA_STRING(chars: (char*)(uintptr_t)key);
18231 return UA_KeyValueMap_getQualified(map, mapSize, key: &qnKey);
18232}
18233
18234/* Returns NULL if the parameter is not defined or not of the right datatype */
18235const UA_Variant *
18236UA_KeyValueMap_getScalar(UA_KeyValuePair *map, size_t mapSize,
18237 const char *key, const UA_DataType *type) {
18238 const UA_Variant *v = UA_KeyValueMap_get(map, mapSize, key);
18239 if(!v || !UA_Variant_hasScalarType(v, type))
18240 return NULL;
18241 return v;
18242}
18243
18244const UA_Variant *
18245UA_KeyValueMap_getArray(UA_KeyValuePair *map, size_t mapSize,
18246 const char *key, const UA_DataType *type) {
18247 const UA_Variant *v = UA_KeyValueMap_get(map, mapSize, key);
18248 if(!v || !UA_Variant_hasArrayType(v, type))
18249 return NULL;
18250 return v;
18251}
18252
18253void
18254UA_KeyValueMap_deleteQualified(UA_KeyValuePair **map, size_t *mapSize,
18255 const UA_QualifiedName *key) {
18256 UA_KeyValuePair *m = *map;
18257 size_t s = *mapSize;
18258 for(size_t i = 0; i < s; i++) {
18259 if(m[i].key.namespaceIndex != key->namespaceIndex ||
18260 !UA_String_equal(s1: &m[i].key.name, s2: &key->name))
18261 continue;
18262
18263 /* Clean the pair */
18264 UA_KeyValuePair_clear(p: &m[i]);
18265
18266 /* Move the last pair to fill the empty slot */
18267 if(s > 1 && i < s - 1) {
18268 m[i] = m[s-1];
18269 UA_KeyValuePair_init(p: &m[s-1]);
18270 }
18271
18272 UA_StatusCode res = UA_Array_resize(p: (void**)map, size: mapSize, newSize: *mapSize-1,
18273 type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
18274 (void)res;
18275 *mapSize = s - 1; /* In case resize fails, keep the longer original
18276 * array around. Resize never fails when reducing
18277 * the size to zero. Reduce the size integer in
18278 * any case. */
18279 return;
18280 }
18281}
18282
18283void
18284UA_KeyValueMap_delete(UA_KeyValuePair **map, size_t *mapSize,
18285 const char *key) {
18286 UA_QualifiedName qnKey;
18287 qnKey.namespaceIndex = 0;
18288 qnKey.name = UA_STRING(chars: (char*)(uintptr_t)key);
18289 UA_KeyValueMap_deleteQualified(map, mapSize, key: &qnKey);
18290}
18291
18292/**** amalgamated original file "/src/ua_timer.c" ****/
18293
18294/* This Source Code Form is subject to the terms of the Mozilla Public
18295 * License, v. 2.0. If a copy of the MPL was not distributed with this
18296 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
18297 *
18298 * Copyright 2017, 2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
18299 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
18300 */
18301
18302
18303/* There may be several entries with the same nextTime in the tree. We give them
18304 * an absolute order by considering the memory address to break ties. Because of
18305 * this, the nextTime property cannot be used to lookup specific entries. */
18306static enum aa_cmp
18307cmpDateTime(const UA_DateTime *a, const UA_DateTime *b) {
18308 if(*a < *b)
18309 return AA_CMP_LESS;
18310 if(*a > *b)
18311 return AA_CMP_MORE;
18312 if(a == b)
18313 return AA_CMP_EQ;
18314 if(a < b)
18315 return AA_CMP_LESS;
18316 return AA_CMP_MORE;
18317}
18318
18319/* The identifiers of entries are unique */
18320static enum aa_cmp
18321cmpId(const UA_UInt64 *a, const UA_UInt64 *b) {
18322 if(*a < *b)
18323 return AA_CMP_LESS;
18324 if(*a == *b)
18325 return AA_CMP_EQ;
18326 return AA_CMP_MORE;
18327}
18328
18329static UA_DateTime
18330calculateNextTime(UA_DateTime currentTime, UA_DateTime baseTime,
18331 UA_DateTime interval) {
18332 /* Take the difference between current and base time */
18333 UA_DateTime diffCurrentTimeBaseTime = currentTime - baseTime;
18334
18335 /* Take modulo of the diff time with the interval. This is the duration we
18336 * are already "into" the current interval. Subtract it from (current +
18337 * interval) to get the next execution time. */
18338 UA_DateTime cycleDelay = diffCurrentTimeBaseTime % interval;
18339
18340 /* Handle the special case where the baseTime is in the future */
18341 if(UA_UNLIKELY(cycleDelay < 0))
18342 cycleDelay += interval;
18343
18344 return currentTime + interval - cycleDelay;
18345}
18346
18347void
18348UA_Timer_init(UA_Timer *t) {
18349 memset(s: t, c: 0, n: sizeof(UA_Timer));
18350 aa_init(head: &t->root,
18351 cmp: (enum aa_cmp (*)(const void*, const void*))cmpDateTime,
18352 offsetof(UA_TimerEntry, treeEntry),
18353 offsetof(UA_TimerEntry, nextTime));
18354 aa_init(head: &t->idRoot,
18355 cmp: (enum aa_cmp (*)(const void*, const void*))cmpId,
18356 offsetof(UA_TimerEntry, idTreeEntry),
18357 offsetof(UA_TimerEntry, id));
18358 UA_LOCK_INIT(&t->timerMutex);
18359}
18360
18361void
18362UA_Timer_addTimerEntry(UA_Timer *t, UA_TimerEntry *te, UA_UInt64 *callbackId) {
18363 UA_LOCK(&t->timerMutex);
18364 te->id = ++t->idCounter;
18365 if(callbackId)
18366 *callbackId = te->id;
18367 aa_insert(head: &t->root, elem: te);
18368 aa_insert(head: &t->idRoot, elem: te);
18369 UA_UNLOCK(&t->timerMutex);
18370}
18371
18372static UA_StatusCode
18373addCallback(UA_Timer *t, UA_ApplicationCallback callback, void *application,
18374 void *data, UA_DateTime nextTime, UA_UInt64 interval,
18375 UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId) {
18376 /* A callback method needs to be present */
18377 if(!callback)
18378 return UA_STATUSCODE_BADINTERNALERROR;
18379
18380 /* Allocate the repeated callback structure */
18381 UA_TimerEntry *te = (UA_TimerEntry*)UA_malloc(size: sizeof(UA_TimerEntry));
18382 if(!te)
18383 return UA_STATUSCODE_BADOUTOFMEMORY;
18384
18385 /* Set the repeated callback */
18386 te->interval = (UA_UInt64)interval;
18387 te->id = ++t->idCounter;
18388 te->callback = callback;
18389 te->application = application;
18390 te->data = data;
18391 te->nextTime = nextTime;
18392 te->timerPolicy = timerPolicy;
18393
18394 /* Set the output identifier */
18395 if(callbackId)
18396 *callbackId = te->id;
18397
18398 aa_insert(head: &t->root, elem: te);
18399 aa_insert(head: &t->idRoot, elem: te);
18400 return UA_STATUSCODE_GOOD;
18401}
18402
18403UA_StatusCode
18404UA_Timer_addTimedCallback(UA_Timer *t, UA_ApplicationCallback callback,
18405 void *application, void *data, UA_DateTime date,
18406 UA_UInt64 *callbackId) {
18407 UA_LOCK(&t->timerMutex);
18408 UA_StatusCode res = addCallback(t, callback, application, data, nextTime: date,
18409 interval: 0, timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
18410 callbackId);
18411 UA_UNLOCK(&t->timerMutex);
18412 return res;
18413}
18414
18415/* Adding repeated callbacks: Add an entry with the "nextTime" timestamp in the
18416 * future. This will be picked up in the next iteration and inserted at the
18417 * correct place. So that the next execution takes place ät "nextTime". */
18418UA_StatusCode
18419UA_Timer_addRepeatedCallback(UA_Timer *t, UA_ApplicationCallback callback,
18420 void *application, void *data, UA_Double interval_ms,
18421 UA_DateTime *baseTime, UA_TimerPolicy timerPolicy,
18422 UA_UInt64 *callbackId) {
18423 /* The interval needs to be positive */
18424 if(interval_ms <= 0.0)
18425 return UA_STATUSCODE_BADINTERNALERROR;
18426 UA_UInt64 interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC);
18427 if(interval == 0)
18428 return UA_STATUSCODE_BADINTERNALERROR;
18429
18430 /* Compute the first time for execution */
18431 UA_DateTime currentTime = UA_DateTime_nowMonotonic();
18432 UA_DateTime nextTime;
18433 if(baseTime == NULL) {
18434 /* Use "now" as the basetime */
18435 nextTime = currentTime + (UA_DateTime)interval;
18436 } else {
18437 nextTime = calculateNextTime(currentTime, baseTime: *baseTime, interval: (UA_DateTime)interval);
18438 }
18439
18440 UA_LOCK(&t->timerMutex);
18441 UA_StatusCode res = addCallback(t, callback, application, data, nextTime,
18442 interval, timerPolicy, callbackId);
18443 UA_UNLOCK(&t->timerMutex);
18444 return res;
18445}
18446
18447UA_StatusCode
18448UA_Timer_changeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId,
18449 UA_Double interval_ms, UA_DateTime *baseTime,
18450 UA_TimerPolicy timerPolicy) {
18451 /* The interval needs to be positive */
18452 if(interval_ms <= 0.0)
18453 return UA_STATUSCODE_BADINTERNALERROR;
18454 UA_UInt64 interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC);
18455 if(interval == 0)
18456 return UA_STATUSCODE_BADINTERNALERROR;
18457
18458 UA_LOCK(&t->timerMutex);
18459
18460 /* Remove from the sorted tree */
18461 UA_TimerEntry *te = (UA_TimerEntry*)aa_find(head: &t->idRoot, key: &callbackId);
18462 if(!te) {
18463 UA_UNLOCK(&t->timerMutex);
18464 return UA_STATUSCODE_BADNOTFOUND;
18465 }
18466 aa_remove(head: &t->root, elem: te);
18467
18468 /* Compute the next time for execution. The logic is identical to the
18469 * creation of a new repeated callback. */
18470 UA_DateTime currentTime = UA_DateTime_nowMonotonic();
18471 if(baseTime == NULL) {
18472 /* Use "now" as the basetime */
18473 te->nextTime = currentTime + (UA_DateTime)interval;
18474 } else {
18475 te->nextTime = calculateNextTime(currentTime, baseTime: *baseTime, interval: (UA_DateTime)interval);
18476 }
18477
18478 /* Update the remaining parameters and re-insert */
18479 te->interval = interval;
18480 te->timerPolicy = timerPolicy;
18481 aa_insert(head: &t->root, elem: te);
18482
18483 UA_UNLOCK(&t->timerMutex);
18484 return UA_STATUSCODE_GOOD;
18485}
18486
18487void
18488UA_Timer_removeCallback(UA_Timer *t, UA_UInt64 callbackId) {
18489 UA_LOCK(&t->timerMutex);
18490 UA_TimerEntry *te = (UA_TimerEntry*)aa_find(head: &t->idRoot, key: &callbackId);
18491 if(UA_LIKELY(te != NULL)) {
18492 aa_remove(head: &t->root, elem: te);
18493 aa_remove(head: &t->idRoot, elem: te);
18494 UA_free(ptr: te);
18495 }
18496 UA_UNLOCK(&t->timerMutex);
18497}
18498
18499UA_DateTime
18500UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic,
18501 UA_TimerExecutionCallback executionCallback,
18502 void *executionApplication) {
18503 UA_LOCK(&t->timerMutex);
18504 UA_TimerEntry *first;
18505 while((first = (UA_TimerEntry*)aa_min(head: &t->root)) &&
18506 first->nextTime <= nowMonotonic) {
18507 aa_remove(head: &t->root, elem: first);
18508
18509 /* Reinsert / remove to their new position first. Because the callback
18510 * can interact with the zip tree and expects the same entries in the
18511 * root and idRoot trees. */
18512
18513 if(first->interval == 0) {
18514 aa_remove(head: &t->idRoot, elem: first);
18515 if(first->callback) {
18516 UA_UNLOCK(&t->timerMutex);
18517 executionCallback(executionApplication, first->callback,
18518 first->application, first->data);
18519 UA_LOCK(&t->timerMutex);
18520 }
18521 UA_free(ptr: first);
18522 continue;
18523 }
18524
18525 /* Set the time for the next execution. Prevent an infinite loop by
18526 * forcing the execution time in the next iteration.
18527 *
18528 * If the timer policy is "CurrentTime", then there is at least the
18529 * interval between executions. This is used for Monitoreditems, for
18530 * which the spec says: The sampling interval indicates the fastest rate
18531 * at which the Server should sample its underlying source for data
18532 * changes. (Part 4, 5.12.1.2) */
18533 first->nextTime += (UA_DateTime)first->interval;
18534 if(first->nextTime < nowMonotonic) {
18535 if(first->timerPolicy == UA_TIMER_HANDLE_CYCLEMISS_WITH_BASETIME)
18536 first->nextTime = calculateNextTime(currentTime: nowMonotonic, baseTime: first->nextTime,
18537 interval: (UA_DateTime)first->interval);
18538 else
18539 first->nextTime = nowMonotonic + (UA_DateTime)first->interval;
18540 }
18541
18542 aa_insert(head: &t->root, elem: first);
18543
18544 if(!first->callback)
18545 continue;
18546
18547 /* Unlock the mutes before dropping into the callback. So that the timer
18548 * itself can be edited within the callback. When we return, only the
18549 * pointer to t must still exist. */
18550 UA_ApplicationCallback cb = first->callback;
18551 void *app = first->application;
18552 void *data = first->data;
18553 UA_UNLOCK(&t->timerMutex);
18554 executionCallback(executionApplication, cb, app, data);
18555 UA_LOCK(&t->timerMutex);
18556 }
18557
18558 /* Return the timestamp of the earliest next callback */
18559 first = (UA_TimerEntry*)aa_min(head: &t->root);
18560 UA_DateTime next = (first) ? first->nextTime : UA_INT64_MAX;
18561 if(next < nowMonotonic)
18562 next = nowMonotonic;
18563 UA_UNLOCK(&t->timerMutex);
18564 return next;
18565}
18566
18567void
18568UA_Timer_clear(UA_Timer *t) {
18569 UA_LOCK(&t->timerMutex);
18570
18571 /* Free all entries */
18572 UA_TimerEntry *top;
18573 while((top = (UA_TimerEntry*)aa_min(head: &t->idRoot))) {
18574 aa_remove(head: &t->idRoot, elem: top);
18575 UA_free(ptr: top);
18576 }
18577
18578 /* Reset the trees to avoid future access */
18579 t->root.root = NULL;
18580 t->idRoot.root = NULL;
18581
18582 UA_UNLOCK(&t->timerMutex);
18583#if UA_MULTITHREADING >= 100
18584 UA_LOCK_DESTROY(&t->timerMutex);
18585#endif
18586}
18587
18588/**** amalgamated original file "/src/ua_connection.c" ****/
18589
18590/* This Source Code Form is subject to the terms of the Mozilla Public
18591 * License, v. 2.0. If a copy of the MPL was not distributed with this
18592 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
18593 *
18594 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
18595 * Copyright 2014, 2016-2017 (c) Florian Palm
18596 * Copyright 2015-2016 (c) Sten Grüner
18597 * Copyright 2015 (c) Oleksiy Vasylyev
18598 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
18599 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
18600 * Copyright 2019 (c) Kalycito Infotech Private Limited
18601 */
18602
18603
18604
18605/* Hides some errors before sending them to a client according to the
18606 * standard. */
18607static void
18608hideErrors(UA_TcpErrorMessage *const error) {
18609 switch(error->error) {
18610 case UA_STATUSCODE_BADCERTIFICATEUNTRUSTED:
18611 case UA_STATUSCODE_BADCERTIFICATEREVOKED:
18612 error->error = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
18613 error->reason = UA_STRING_NULL;
18614 break;
18615 // TODO: Check if these are all cases that need to be covered.
18616 default:
18617 break;
18618 }
18619}
18620
18621void
18622UA_Connection_sendError(UA_Connection *connection, UA_TcpErrorMessage *error) {
18623 hideErrors(error);
18624
18625 UA_TcpMessageHeader header;
18626 header.messageTypeAndChunkType = UA_MESSAGETYPE_ERR + UA_CHUNKTYPE_FINAL;
18627 // Header + ErrorMessage (error + reasonLength_field + length)
18628 header.messageSize = 8 + (4 + 4 + (UA_UInt32)error->reason.length);
18629
18630 /* Get the send buffer from the network layer */
18631 UA_ByteString msg = UA_BYTESTRING_NULL;
18632 UA_StatusCode retval = connection->getSendBuffer(connection, header.messageSize, &msg);
18633 if(retval != UA_STATUSCODE_GOOD)
18634 return;
18635
18636 /* Encode and send the response */
18637 UA_Byte *bufPos = msg.data;
18638 const UA_Byte *bufEnd = &msg.data[msg.length];
18639 retval |= UA_encodeBinaryInternal(src: &header,
18640 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
18641 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
18642 retval |= UA_encodeBinaryInternal(src: error,
18643 type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE],
18644 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
18645 (void)retval; /* Encoding of these cannot fail */
18646 msg.length = header.messageSize;
18647 connection->send(connection, &msg);
18648}
18649
18650void UA_Connection_detachSecureChannel(UA_Connection *connection) {
18651 UA_SecureChannel *channel = connection->channel;
18652 if(channel)
18653 /* only replace when the channel points to this connection */
18654 UA_atomic_cmpxchg(addr: (void**)&channel->connection, expected: connection, NULL);
18655 UA_atomic_xchg(addr: (void**)&connection->channel, NULL);
18656}
18657
18658// TODO: Return an error code
18659void
18660UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel) {
18661 if(UA_atomic_cmpxchg(addr: (void**)&channel->connection, NULL, newptr: connection) == NULL)
18662 UA_atomic_xchg(addr: (void**)&connection->channel, newptr: (void*)channel);
18663}
18664
18665/**** amalgamated original file "/src/ua_securechannel.c" ****/
18666
18667/* This Source Code Form is subject to the terms of the Mozilla Public
18668 * License, v. 2.0. If a copy of the MPL was not distributed with this
18669 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
18670 *
18671 * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
18672 * Copyright 2014, 2016-2017 (c) Florian Palm
18673 * Copyright 2015-2016 (c) Sten Grüner
18674 * Copyright 2015 (c) Oleksiy Vasylyev
18675 * Copyright 2016 (c) TorbenD
18676 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
18677 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
18678 * Copyright 2018-2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
18679 */
18680
18681
18682
18683#define UA_BITMASK_MESSAGETYPE 0x00ffffffu
18684#define UA_BITMASK_CHUNKTYPE 0xff000000u
18685
18686const UA_String UA_SECURITY_POLICY_NONE_URI =
18687 {47, (UA_Byte *)"http://opcfoundation.org/UA/SecurityPolicy#None"};
18688
18689#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
18690UA_StatusCode decrypt_verifySignatureFailure;
18691UA_StatusCode sendAsym_sendFailure;
18692UA_StatusCode processSym_seqNumberFailure;
18693#endif
18694
18695void UA_SecureChannel_init(UA_SecureChannel *channel,
18696 const UA_ConnectionConfig *config) {
18697 /* Linked lists are also initialized by zeroing out */
18698 memset(s: channel, c: 0, n: sizeof(UA_SecureChannel));
18699 channel->state = UA_SECURECHANNELSTATE_FRESH;
18700 SIMPLEQ_INIT(&channel->completeChunks);
18701 SIMPLEQ_INIT(&channel->decryptedChunks);
18702 SLIST_INIT(&channel->sessions);
18703 channel->config = *config;
18704}
18705
18706UA_StatusCode
18707UA_SecureChannel_setSecurityPolicy(UA_SecureChannel *channel,
18708 const UA_SecurityPolicy *securityPolicy,
18709 const UA_ByteString *remoteCertificate) {
18710 /* Is a policy already configured? */
18711 UA_CHECK_ERROR(!channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR,
18712 securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
18713 "Security policy already configured");
18714
18715 /* Create the context */
18716 UA_StatusCode res = securityPolicy->channelModule.
18717 newContext(securityPolicy, remoteCertificate, &channel->channelContext);
18718 res |= UA_ByteString_copy(src: remoteCertificate, dst: &channel->remoteCertificate);
18719 UA_CHECK_STATUS_WARN(res, return res, securityPolicy->logger,
18720 UA_LOGCATEGORY_SECURITYPOLICY,
18721 "Could not set up the SecureChannel context");
18722
18723 /* Compute the certificate thumbprint */
18724 UA_ByteString remoteCertificateThumbprint =
18725 {20, channel->remoteCertificateThumbprint};
18726 res = securityPolicy->asymmetricModule.
18727 makeCertificateThumbprint(securityPolicy, &channel->remoteCertificate,
18728 &remoteCertificateThumbprint);
18729 UA_CHECK_STATUS_WARN(res, return res, securityPolicy->logger,
18730 UA_LOGCATEGORY_SECURITYPOLICY,
18731 "Could not create the certificate thumbprint");
18732
18733 /* Set the policy */
18734 channel->securityPolicy = securityPolicy;
18735 return UA_STATUSCODE_GOOD;
18736}
18737
18738static void
18739UA_Chunk_delete(UA_Chunk *chunk) {
18740 if(chunk->copied)
18741 UA_ByteString_clear(p: &chunk->bytes);
18742 UA_free(ptr: chunk);
18743}
18744
18745static void
18746deleteChunks(UA_ChunkQueue *queue) {
18747 UA_Chunk *chunk;
18748 while((chunk = SIMPLEQ_FIRST(queue))) {
18749 SIMPLEQ_REMOVE_HEAD(queue, pointers);
18750 UA_Chunk_delete(chunk);
18751 }
18752}
18753
18754void
18755UA_SecureChannel_deleteBuffered(UA_SecureChannel *channel) {
18756 deleteChunks(queue: &channel->completeChunks);
18757 deleteChunks(queue: &channel->decryptedChunks);
18758 UA_ByteString_clear(p: &channel->incompleteChunk);
18759}
18760
18761void
18762UA_SecureChannel_close(UA_SecureChannel *channel) {
18763 /* Set the status to closed */
18764 channel->state = UA_SECURECHANNELSTATE_CLOSED;
18765
18766 /* Detach from the connection and close the connection */
18767 if(channel->connection) {
18768 if(channel->connection->state != UA_CONNECTIONSTATE_CLOSED)
18769 channel->connection->close(channel->connection);
18770 UA_Connection_detachSecureChannel(connection: channel->connection);
18771 }
18772
18773 /* Detach Sessions from the SecureChannel. This also removes outstanding
18774 * Publish requests whose RequestId is valid only for the SecureChannel. */
18775 UA_SessionHeader *sh;
18776 while((sh = SLIST_FIRST(&channel->sessions))) {
18777 if(sh->serverSession) {
18778 UA_Session_detachFromSecureChannel(session: (UA_Session *)sh);
18779 } else {
18780 sh->channel = NULL;
18781 SLIST_REMOVE_HEAD(&channel->sessions, next);
18782 }
18783 }
18784
18785 /* Delete the channel context for the security policy */
18786 if(channel->securityPolicy) {
18787 channel->securityPolicy->channelModule.deleteContext(channel->channelContext);
18788 channel->securityPolicy = NULL;
18789 channel->channelContext = NULL;
18790 }
18791
18792 /* Delete members */
18793 UA_ByteString_clear(p: &channel->remoteCertificate);
18794 UA_ByteString_clear(p: &channel->localNonce);
18795 UA_ByteString_clear(p: &channel->remoteNonce);
18796 UA_ChannelSecurityToken_clear(p: &channel->securityToken);
18797 UA_ChannelSecurityToken_clear(p: &channel->altSecurityToken);
18798 UA_SecureChannel_deleteBuffered(channel);
18799}
18800
18801UA_StatusCode
18802UA_SecureChannel_processHELACK(UA_SecureChannel *channel,
18803 const UA_TcpAcknowledgeMessage *remoteConfig) {
18804 /* The lowest common version is used by both sides */
18805 if(channel->config.protocolVersion > remoteConfig->protocolVersion)
18806 channel->config.protocolVersion = remoteConfig->protocolVersion;
18807
18808 /* Can we receive the max send size? */
18809 if(channel->config.sendBufferSize > remoteConfig->receiveBufferSize)
18810 channel->config.sendBufferSize = remoteConfig->receiveBufferSize;
18811
18812 /* Can we send the max receive size? */
18813 if(channel->config.recvBufferSize > remoteConfig->sendBufferSize)
18814 channel->config.recvBufferSize = remoteConfig->sendBufferSize;
18815
18816 channel->config.remoteMaxMessageSize = remoteConfig->maxMessageSize;
18817 channel->config.remoteMaxChunkCount = remoteConfig->maxChunkCount;
18818
18819 /* Chunks of at least 8192 bytes must be permissible.
18820 * See Part 6, Clause 6.7.1 */
18821 if(channel->config.recvBufferSize < 8192 ||
18822 channel->config.sendBufferSize < 8192 ||
18823 (channel->config.remoteMaxMessageSize != 0 &&
18824 channel->config.remoteMaxMessageSize < 8192))
18825 return UA_STATUSCODE_BADINTERNALERROR;
18826
18827 channel->connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
18828 return UA_STATUSCODE_GOOD;
18829}
18830
18831/* Sends an OPN message using asymmetric encryption if defined */
18832UA_StatusCode
18833UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
18834 UA_UInt32 requestId, const void *content,
18835 const UA_DataType *contentType) {
18836 UA_CHECK(channel->securityMode != UA_MESSAGESECURITYMODE_INVALID,
18837 return UA_STATUSCODE_BADSECURITYMODEREJECTED);
18838
18839 const UA_SecurityPolicy *sp = channel->securityPolicy;
18840 UA_Connection *conn = channel->connection;
18841 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
18842 UA_CHECK_MEM(conn, return UA_STATUSCODE_BADINTERNALERROR);
18843
18844 /* Allocate the message buffer */
18845 UA_ByteString buf = UA_BYTESTRING_NULL;
18846 UA_StatusCode res = conn->getSendBuffer(conn, channel->config.sendBufferSize, &buf);
18847 UA_CHECK_STATUS(res, return res);
18848
18849 /* Restrict buffer to the available space for the payload */
18850 UA_Byte *buf_pos = buf.data;
18851 const UA_Byte *buf_end = &buf.data[buf.length];
18852 hideBytesAsym(channel, buf_start: &buf_pos, buf_end: &buf_end);
18853
18854 /* Encode the message type and content */
18855 res |= UA_NodeId_encodeBinary(src: &contentType->binaryEncodingId, bufPos: &buf_pos, bufEnd: buf_end);
18856 res |= UA_encodeBinaryInternal(src: content, type: contentType,
18857 bufPos: &buf_pos, bufEnd: &buf_end, NULL, NULL);
18858 UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
18859
18860 const size_t securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel);
18861
18862#ifdef UA_ENABLE_ENCRYPTION
18863 /* Add padding to the chunk. Also pad if the securityMode is SIGN_ONLY,
18864 * since we are using asymmetric communication to exchange keys and thus
18865 * need to encrypt. */
18866 if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE)
18867 padChunk(channel, cm: &channel->securityPolicy->asymmetricModule.cryptoModule,
18868 start: &buf.data[UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength],
18869 pos: &buf_pos);
18870#endif
18871
18872 /* The total message length */
18873 size_t pre_sig_length = (uintptr_t)buf_pos - (uintptr_t)buf.data;
18874 size_t total_length = pre_sig_length;
18875 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
18876 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
18877 total_length += sp->asymmetricModule.cryptoModule.signatureAlgorithm.
18878 getLocalSignatureSize(channel->channelContext);
18879
18880 /* The total message length is known here which is why we encode the headers
18881 * at this step and not earlier. */
18882 size_t encryptedLength = 0;
18883 res = prependHeadersAsym(channel, header_pos: buf.data, buf_end, totalLength: total_length,
18884 securityHeaderLength, requestId, finalLength: &encryptedLength);
18885 UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
18886
18887#ifdef UA_ENABLE_ENCRYPTION
18888 res = signAndEncryptAsym(channel, preSignLength: pre_sig_length, buf: &buf,
18889 securityHeaderLength, totalLength: total_length);
18890 UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
18891#endif
18892
18893 /* Send the message, the buffer is freed in the network layer */
18894 buf.length = encryptedLength;
18895 res = conn->send(conn, &buf);
18896#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
18897 res |= sendAsym_sendFailure;
18898#endif
18899 return res;
18900}
18901
18902/* Will this chunk surpass the capacity of the SecureChannel for the message? */
18903static UA_StatusCode
18904adjustCheckMessageLimitsSym(UA_MessageContext *mc, size_t bodyLength) {
18905 mc->messageSizeSoFar += bodyLength;
18906 mc->chunksSoFar++;
18907
18908 UA_SecureChannel *channel = mc->channel;
18909 if(mc->messageSizeSoFar > channel->config.localMaxMessageSize &&
18910 channel->config.localMaxMessageSize != 0)
18911 return UA_STATUSCODE_BADRESPONSETOOLARGE;
18912
18913 if(mc->chunksSoFar > channel->config.localMaxChunkCount &&
18914 channel->config.localMaxChunkCount != 0)
18915 return UA_STATUSCODE_BADRESPONSETOOLARGE;
18916
18917 return UA_STATUSCODE_GOOD;
18918}
18919
18920static UA_StatusCode
18921encodeHeadersSym(UA_MessageContext *mc, size_t totalLength) {
18922 UA_SecureChannel *channel = mc->channel;
18923 UA_Byte *header_pos = mc->messageBuffer.data;
18924
18925 UA_TcpMessageHeader header;
18926 header.messageTypeAndChunkType = mc->messageType;
18927 header.messageSize = (UA_UInt32)totalLength;
18928 if(mc->final)
18929 header.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
18930 else
18931 header.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE;
18932
18933 UA_SequenceHeader seqHeader;
18934 seqHeader.requestId = mc->requestId;
18935 seqHeader.sequenceNumber = UA_atomic_addUInt32(addr: &channel->sendSequenceNumber, increase: 1);
18936
18937 UA_StatusCode res = UA_STATUSCODE_GOOD;
18938 res |= UA_encodeBinaryInternal(src: &header, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
18939 bufPos: &header_pos, bufEnd: &mc->buf_end, NULL, NULL);
18940 res |= UA_UInt32_encodeBinary(src: &channel->securityToken.channelId,
18941 bufPos: &header_pos, bufEnd: mc->buf_end);
18942 res |= UA_UInt32_encodeBinary(src: &channel->securityToken.tokenId,
18943 bufPos: &header_pos, bufEnd: mc->buf_end);
18944 res |= UA_encodeBinaryInternal(src: &seqHeader, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
18945 bufPos: &header_pos, bufEnd: &mc->buf_end, NULL, NULL);
18946 return res;
18947}
18948
18949static UA_StatusCode
18950sendSymmetricChunk(UA_MessageContext *mc) {
18951 UA_SecureChannel *channel = mc->channel;
18952 const UA_SecurityPolicy *sp = channel->securityPolicy;
18953 UA_Connection *connection = channel->connection;
18954 UA_CHECK_MEM(connection, return UA_STATUSCODE_BADINTERNALERROR);
18955
18956 /* The size of the message payload */
18957 size_t bodyLength = (uintptr_t)mc->buf_pos -
18958 (uintptr_t)&mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
18959
18960 /* Early-declare variables so we can use a goto in the error case */
18961 size_t total_length = 0;
18962 size_t pre_sig_length = 0;
18963
18964 /* Check if chunk exceeds the limits for the overall message */
18965 UA_StatusCode res = adjustCheckMessageLimitsSym(mc, bodyLength);
18966 UA_CHECK_STATUS(res, goto error);
18967
18968 UA_LOG_TRACE_CHANNEL(sp->logger, channel,
18969 "Send from a symmetric message buffer of length %lu "
18970 "a message of header+payload length of %lu",
18971 (long unsigned int)mc->messageBuffer.length,
18972 (long unsigned int)
18973 ((uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data));
18974
18975#ifdef UA_ENABLE_ENCRYPTION
18976 /* Add padding if the message is encrypted */
18977 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
18978 padChunk(channel, cm: &sp->symmetricModule.cryptoModule,
18979 start: &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_UNENCRYPTEDLENGTH],
18980 pos: &mc->buf_pos);
18981#endif
18982
18983 /* Compute the total message length */
18984 pre_sig_length = (uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data;
18985 total_length = pre_sig_length;
18986 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
18987 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
18988 total_length += sp->symmetricModule.cryptoModule.signatureAlgorithm.
18989 getLocalSignatureSize(channel->channelContext);
18990
18991 UA_LOG_TRACE_CHANNEL(sp->logger, channel,
18992 "Send from a symmetric message buffer of length %lu "
18993 "a message of length %lu",
18994 (long unsigned int)mc->messageBuffer.length,
18995 (long unsigned int)total_length);
18996
18997 /* Space for the padding and the signature have been reserved in setBufPos() */
18998 UA_assert(total_length <= channel->config.sendBufferSize);
18999
19000 /* Adjust the buffer size of the network layer */
19001 mc->messageBuffer.length = total_length;
19002
19003 /* Generate and encode the header for symmetric messages */
19004 res = encodeHeadersSym(mc, totalLength: total_length);
19005 UA_CHECK_STATUS(res, goto error);
19006
19007#ifdef UA_ENABLE_ENCRYPTION
19008 /* Sign and encrypt the messge */
19009 res = signAndEncryptSym(messageContext: mc, preSigLength: pre_sig_length, totalLength: total_length);
19010 UA_CHECK_STATUS(res, goto error);
19011#endif
19012
19013 /* Send the chunk, the buffer is freed in the network layer */
19014 return connection->send(channel->connection, &mc->messageBuffer);
19015
19016 error:
19017 /* Free the unused message buffer */
19018 connection->releaseSendBuffer(channel->connection, &mc->messageBuffer);
19019 return res;
19020}
19021
19022/* Callback from the encoding layer. Send the chunk and replace the buffer. */
19023static UA_StatusCode
19024sendSymmetricEncodingCallback(void *data, UA_Byte **buf_pos,
19025 const UA_Byte **buf_end) {
19026 /* Set buf values from encoding in the messagecontext */
19027 UA_MessageContext *mc = (UA_MessageContext *)data;
19028 mc->buf_pos = *buf_pos;
19029 mc->buf_end = *buf_end;
19030
19031 /* Send out */
19032 UA_StatusCode res = sendSymmetricChunk(mc);
19033 UA_CHECK_STATUS(res, return res);
19034
19035 /* Set a new buffer for the next chunk */
19036 UA_Connection *c = mc->channel->connection;
19037 UA_CHECK_MEM(c, return UA_STATUSCODE_BADINTERNALERROR);
19038
19039 res = c->getSendBuffer(c, mc->channel->config.sendBufferSize,
19040 &mc->messageBuffer);
19041 UA_CHECK_STATUS(res, return res);
19042
19043 /* Hide bytes for header, padding and signature */
19044 setBufPos(mc);
19045 *buf_pos = mc->buf_pos;
19046 *buf_end = mc->buf_end;
19047 return UA_STATUSCODE_GOOD;
19048}
19049
19050UA_StatusCode
19051UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
19052 UA_UInt32 requestId, UA_MessageType messageType) {
19053 UA_CHECK(messageType == UA_MESSAGETYPE_MSG || messageType == UA_MESSAGETYPE_CLO,
19054 return UA_STATUSCODE_BADINTERNALERROR);
19055
19056 UA_Connection *c = channel->connection;
19057 UA_CHECK_MEM(c, return UA_STATUSCODE_BADINTERNALERROR);
19058
19059 /* Create the chunking info structure */
19060 mc->channel = channel;
19061 mc->requestId = requestId;
19062 mc->chunksSoFar = 0;
19063 mc->messageSizeSoFar = 0;
19064 mc->final = false;
19065 mc->messageBuffer = UA_BYTESTRING_NULL;
19066 mc->messageType = messageType;
19067
19068 /* Allocate the message buffer */
19069 UA_StatusCode res = c->getSendBuffer(c, channel->config.sendBufferSize,
19070 &mc->messageBuffer);
19071 UA_CHECK_STATUS(res, return res);
19072
19073 /* Hide bytes for header, padding and signature */
19074 setBufPos(mc);
19075 return UA_STATUSCODE_GOOD;
19076}
19077
19078UA_StatusCode
19079UA_MessageContext_encode(UA_MessageContext *mc, const void *content,
19080 const UA_DataType *contentType) {
19081 UA_StatusCode res =
19082 UA_encodeBinaryInternal(src: content, type: contentType, bufPos: &mc->buf_pos, bufEnd: &mc->buf_end,
19083 exchangeCallback: sendSymmetricEncodingCallback, exchangeHandle: mc);
19084 if(res != UA_STATUSCODE_GOOD && mc->messageBuffer.length > 0)
19085 UA_MessageContext_abort(mc);
19086 return res;
19087}
19088
19089UA_StatusCode
19090UA_MessageContext_finish(UA_MessageContext *mc) {
19091 mc->final = true;
19092 return sendSymmetricChunk(mc);
19093}
19094
19095void
19096UA_MessageContext_abort(UA_MessageContext *mc) {
19097 UA_Connection *connection = mc->channel->connection;
19098 connection->releaseSendBuffer(connection, &mc->messageBuffer);
19099}
19100
19101UA_StatusCode
19102UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
19103 UA_MessageType messageType, void *payload,
19104 const UA_DataType *payloadType) {
19105 if(!channel || !channel->connection || !payload || !payloadType)
19106 return UA_STATUSCODE_BADINTERNALERROR;
19107
19108 if(channel->state != UA_SECURECHANNELSTATE_OPEN)
19109 return UA_STATUSCODE_BADCONNECTIONCLOSED;
19110
19111 if(channel->connection->state != UA_CONNECTIONSTATE_ESTABLISHED)
19112 return UA_STATUSCODE_BADCONNECTIONCLOSED;
19113
19114 UA_MessageContext mc;
19115 UA_StatusCode res = UA_MessageContext_begin(mc: &mc, channel, requestId, messageType);
19116 UA_CHECK_STATUS(res, return res);
19117
19118 /* Assert's required for clang-analyzer */
19119 UA_assert(mc.buf_pos ==
19120 &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]);
19121 UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]);
19122
19123 res = UA_MessageContext_encode(mc: &mc, content: &payloadType->binaryEncodingId,
19124 contentType: &UA_TYPES[UA_TYPES_NODEID]);
19125 UA_CHECK_STATUS(res, return res);
19126
19127 res = UA_MessageContext_encode(mc: &mc, content: payload, contentType: payloadType);
19128 UA_CHECK_STATUS(res, return res);
19129
19130 return UA_MessageContext_finish(mc: &mc);
19131}
19132
19133/********************************/
19134/* Receive and Process Messages */
19135/********************************/
19136
19137/* Does the sequence number match? Otherwise try to rollover. See Part 6,
19138 * Section 6.7.2.4 of the standard. */
19139#define UA_SEQUENCENUMBER_ROLLOVER 4294966271
19140
19141#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
19142static UA_StatusCode
19143processSequenceNumberSym(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) {
19144#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
19145 /* Failure mode hook for unit tests */
19146 if(processSym_seqNumberFailure != UA_STATUSCODE_GOOD)
19147 return processSym_seqNumberFailure;
19148#endif
19149
19150 if(sequenceNumber != channel->receiveSequenceNumber + 1) {
19151 if(channel->receiveSequenceNumber + 1 <= UA_SEQUENCENUMBER_ROLLOVER ||
19152 sequenceNumber >= 1024)
19153 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
19154 channel->receiveSequenceNumber = sequenceNumber - 1; /* Roll over */
19155 }
19156 ++channel->receiveSequenceNumber;
19157 return UA_STATUSCODE_GOOD;
19158}
19159#endif
19160
19161static UA_StatusCode
19162unpackPayloadOPN(UA_SecureChannel *channel, UA_Chunk *chunk, void *application) {
19163 UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
19164 size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */
19165 UA_UInt32 secureChannelId;
19166 UA_StatusCode res = UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &secureChannelId);
19167 UA_assert(res == UA_STATUSCODE_GOOD);
19168
19169 UA_AsymmetricAlgorithmSecurityHeader asymHeader;
19170 res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &asymHeader,
19171 type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], NULL);
19172 UA_CHECK_STATUS(res, return res);
19173
19174 if(asymHeader.senderCertificate.length > 0) {
19175 if(channel->certificateVerification)
19176 res = channel->certificateVerification->
19177 verifyCertificate(channel->certificateVerification->context,
19178 &asymHeader.senderCertificate);
19179 else
19180 res = UA_STATUSCODE_BADINTERNALERROR;
19181 UA_CHECK_STATUS(res, goto error);
19182 }
19183
19184 /* New channel, create a security policy context and attach */
19185 if(!channel->securityPolicy) {
19186 if(channel->processOPNHeader)
19187 res = channel->processOPNHeader(application, channel, &asymHeader);
19188 if(!channel->securityPolicy)
19189 res = UA_STATUSCODE_BADINTERNALERROR;
19190 UA_CHECK_STATUS(res, goto error);
19191 }
19192
19193 /* On the client side, take the SecureChannelId from the first response */
19194 if(secureChannelId != 0 && channel->securityToken.channelId == 0)
19195 channel->securityToken.channelId = secureChannelId;
19196
19197#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
19198 /* Check the ChannelId. Non-opened channels have the id zero. */
19199 if(secureChannelId != channel->securityToken.channelId) {
19200 res = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
19201 goto error;
19202 }
19203#endif
19204
19205 /* Check the header */
19206 res = checkAsymHeader(channel, asymHeader: &asymHeader);
19207 UA_AsymmetricAlgorithmSecurityHeader_clear(p: &asymHeader);
19208 UA_CHECK_STATUS(res, return res);
19209
19210 /* Decrypt the chunk payload */
19211 res = decryptAndVerifyChunk(channel,
19212 cryptoModule: &channel->securityPolicy->asymmetricModule.cryptoModule,
19213 messageType: chunk->messageType, chunk: &chunk->bytes, offset);
19214 UA_CHECK_STATUS(res, return res);
19215
19216 /* Decode the SequenceHeader */
19217 UA_SequenceHeader sequenceHeader;
19218 res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &sequenceHeader,
19219 type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
19220 UA_CHECK_STATUS(res, return res);
19221
19222 /* Set the sequence number for the channel from which to count up */
19223 channel->receiveSequenceNumber = sequenceHeader.sequenceNumber;
19224 chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */
19225
19226 /* Use only the payload */
19227 chunk->bytes.data += offset;
19228 chunk->bytes.length -= offset;
19229 return UA_STATUSCODE_GOOD;
19230
19231error:
19232 UA_AsymmetricAlgorithmSecurityHeader_clear(p: &asymHeader);
19233 return res;
19234}
19235
19236static UA_StatusCode
19237unpackPayloadMSG(UA_SecureChannel *channel, UA_Chunk *chunk) {
19238 UA_CHECK_MEM(channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR);
19239
19240 UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
19241 size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */
19242 UA_UInt32 secureChannelId;
19243 UA_UInt32 tokenId; /* SymmetricAlgorithmSecurityHeader */
19244 UA_StatusCode res = UA_STATUSCODE_GOOD;
19245 res |= UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &secureChannelId);
19246 res |= UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &tokenId);
19247 UA_assert(offset == UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
19248 UA_assert(res == UA_STATUSCODE_GOOD);
19249
19250#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
19251 /* Check the ChannelId. Non-opened channels have the id zero. */
19252 UA_CHECK(secureChannelId == channel->securityToken.channelId,
19253 return UA_STATUSCODE_BADSECURECHANNELIDINVALID);
19254#endif
19255
19256 /* Check (and revolve) the SecurityToken */
19257 res = checkSymHeader(channel, tokenId);
19258 UA_CHECK_STATUS(res, return res);
19259
19260 /* Decrypt the chunk payload */
19261 res = decryptAndVerifyChunk(channel,
19262 cryptoModule: &channel->securityPolicy->symmetricModule.cryptoModule,
19263 messageType: chunk->messageType, chunk: &chunk->bytes, offset);
19264 UA_CHECK_STATUS(res, return res);
19265
19266 /* Check the sequence number. Skip sequence number checking for fuzzer to
19267 * improve coverage */
19268 UA_SequenceHeader sequenceHeader;
19269 res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &sequenceHeader,
19270 type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
19271#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
19272 res |= processSequenceNumberSym(channel, sequenceNumber: sequenceHeader.sequenceNumber);
19273#endif
19274 UA_CHECK_STATUS(res, return res);
19275
19276 chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */
19277
19278 /* Use only the payload */
19279 chunk->bytes.data += offset;
19280 chunk->bytes.length -= offset;
19281 return UA_STATUSCODE_GOOD;
19282}
19283
19284static UA_StatusCode
19285assembleProcessMessage(UA_SecureChannel *channel, void *application,
19286 UA_ProcessMessageCallback callback) {
19287 UA_Chunk *chunk = SIMPLEQ_FIRST(&channel->decryptedChunks);
19288 UA_assert(chunk != NULL);
19289
19290 UA_StatusCode res = UA_STATUSCODE_GOOD;
19291 if(chunk->chunkType == UA_CHUNKTYPE_FINAL) {
19292 SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
19293 UA_assert(chunk->chunkType == UA_CHUNKTYPE_FINAL);
19294 res = callback(application, channel, chunk->messageType,
19295 chunk->requestId, &chunk->bytes);
19296 UA_Chunk_delete(chunk);
19297 return res;
19298 }
19299
19300 UA_UInt32 requestId = chunk->requestId;
19301 UA_MessageType messageType = chunk->messageType;
19302 UA_ChunkType chunkType = chunk->chunkType;
19303 UA_assert(chunkType == UA_CHUNKTYPE_INTERMEDIATE);
19304
19305 size_t messageSize = 0;
19306 SIMPLEQ_FOREACH(chunk, &channel->decryptedChunks, pointers) {
19307 /* Consistency check */
19308 if(requestId != chunk->requestId)
19309 return UA_STATUSCODE_BADINTERNALERROR;
19310 if(chunkType != chunk->chunkType && chunk->chunkType != UA_CHUNKTYPE_FINAL)
19311 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19312 if(chunk->messageType != messageType)
19313 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19314
19315 /* Sum up the lengths */
19316 messageSize += chunk->bytes.length;
19317 if(chunk->chunkType == UA_CHUNKTYPE_FINAL)
19318 break;
19319 }
19320
19321 /* Allocate memory for the full message */
19322 UA_ByteString payload;
19323 res = UA_ByteString_allocBuffer(bs: &payload, length: messageSize);
19324 UA_CHECK_STATUS(res, return res);
19325
19326 /* Assemble the full message */
19327 size_t offset = 0;
19328 while(true) {
19329 chunk = SIMPLEQ_FIRST(&channel->decryptedChunks);
19330 memcpy(dest: &payload.data[offset], src: chunk->bytes.data, n: chunk->bytes.length);
19331 offset += chunk->bytes.length;
19332 SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
19333 UA_ChunkType ct = chunk->chunkType;
19334 UA_Chunk_delete(chunk);
19335 if(ct == UA_CHUNKTYPE_FINAL)
19336 break;
19337 }
19338
19339 /* Process the assembled message */
19340 res = callback(application, channel, messageType, requestId, &payload);
19341 UA_ByteString_clear(p: &payload);
19342 return res;
19343}
19344
19345static UA_StatusCode
19346persistCompleteChunks(UA_ChunkQueue *queue) {
19347 UA_Chunk *chunk;
19348 SIMPLEQ_FOREACH(chunk, queue, pointers) {
19349 if(chunk->copied)
19350 continue;
19351 UA_ByteString copy;
19352 UA_StatusCode res = UA_ByteString_copy(src: &chunk->bytes, dst: &copy);
19353 UA_CHECK_STATUS(res, return res);
19354 chunk->bytes = copy;
19355 chunk->copied = true;
19356 }
19357 return UA_STATUSCODE_GOOD;
19358}
19359
19360static UA_StatusCode
19361persistIncompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer,
19362 size_t offset) {
19363 UA_assert(channel->incompleteChunk.length == 0);
19364 UA_assert(offset < buffer->length);
19365 size_t length = buffer->length - offset;
19366 UA_StatusCode res = UA_ByteString_allocBuffer(bs: &channel->incompleteChunk, length);
19367 UA_CHECK_STATUS(res, return res);
19368 memcpy(dest: channel->incompleteChunk.data, src: &buffer->data[offset], n: length);
19369 return UA_STATUSCODE_GOOD;
19370}
19371
19372/* Processes chunks and puts them into the payloads queue. Once a final chunk is
19373 * put into the queue, the message is assembled and the callback is called. The
19374 * queue will be cleared for the next message. */
19375static UA_StatusCode
19376processChunks(UA_SecureChannel *channel, void *application,
19377 UA_ProcessMessageCallback callback) {
19378 UA_Chunk *chunk;
19379 UA_StatusCode res = UA_STATUSCODE_GOOD;
19380 while((chunk = SIMPLEQ_FIRST(&channel->completeChunks))) {
19381 /* Remove from the complete-chunk queue */
19382 SIMPLEQ_REMOVE_HEAD(&channel->completeChunks, pointers);
19383
19384 /* Check, decrypt and unpack the payload */
19385 if(chunk->messageType == UA_MESSAGETYPE_OPN) {
19386 if(channel->state != UA_SECURECHANNELSTATE_OPEN &&
19387 channel->state != UA_SECURECHANNELSTATE_OPN_SENT &&
19388 channel->state != UA_SECURECHANNELSTATE_ACK_SENT)
19389 res = UA_STATUSCODE_BADINVALIDSTATE;
19390 else
19391 res = unpackPayloadOPN(channel, chunk, application);
19392 } else if(chunk->messageType == UA_MESSAGETYPE_MSG ||
19393 chunk->messageType == UA_MESSAGETYPE_CLO) {
19394 if(channel->state == UA_SECURECHANNELSTATE_CLOSED)
19395 res = UA_STATUSCODE_BADSECURECHANNELCLOSED;
19396 else
19397 res = unpackPayloadMSG(channel, chunk);
19398 } else {
19399 chunk->bytes.data += UA_SECURECHANNEL_MESSAGEHEADER_LENGTH;
19400 chunk->bytes.length -= UA_SECURECHANNEL_MESSAGEHEADER_LENGTH;
19401 }
19402
19403 if(res != UA_STATUSCODE_GOOD) {
19404 UA_Chunk_delete(chunk);
19405 return res;
19406 }
19407
19408 /* Add to the decrypted-chunk queue */
19409 SIMPLEQ_INSERT_TAIL(&channel->decryptedChunks, chunk, pointers);
19410
19411 /* Check the resource limits */
19412 channel->decryptedChunksCount++;
19413 channel->decryptedChunksLength += chunk->bytes.length;
19414 if((channel->config.localMaxChunkCount != 0 &&
19415 channel->decryptedChunksCount > channel->config.localMaxChunkCount) ||
19416 (channel->config.localMaxMessageSize != 0 &&
19417 channel->decryptedChunksLength > channel->config.localMaxMessageSize)) {
19418 return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
19419 }
19420
19421 /* Waiting for additional chunks */
19422 if(chunk->chunkType == UA_CHUNKTYPE_INTERMEDIATE)
19423 continue;
19424
19425 /* Final chunk or abort. Reset the counters. */
19426 channel->decryptedChunksCount = 0;
19427 channel->decryptedChunksLength = 0;
19428
19429 /* Abort the message, remove all decrypted chunks
19430 * TODO: Log a warning with the error code */
19431 if(chunk->chunkType == UA_CHUNKTYPE_ABORT) {
19432 while((chunk = SIMPLEQ_FIRST(&channel->decryptedChunks))) {
19433 SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
19434 UA_Chunk_delete(chunk);
19435 }
19436 continue;
19437 }
19438
19439 /* The decrypted queue contains a full message. Process it. */
19440 UA_assert(chunk->chunkType == UA_CHUNKTYPE_FINAL);
19441 res = assembleProcessMessage(channel, application, callback);
19442 UA_CHECK_STATUS(res, return res);
19443 }
19444
19445 return UA_STATUSCODE_GOOD;
19446}
19447
19448static UA_StatusCode
19449extractCompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer,
19450 size_t *offset, UA_Boolean *done) {
19451 /* At least 8 byte needed for the header. Wait for the next chunk. */
19452 size_t initial_offset = *offset;
19453 size_t remaining = buffer->length - initial_offset;
19454 if(remaining < UA_SECURECHANNEL_MESSAGEHEADER_LENGTH) {
19455 *done = true;
19456 return UA_STATUSCODE_GOOD;
19457 }
19458
19459 /* Decoding cannot fail */
19460 UA_TcpMessageHeader hdr;
19461 UA_StatusCode res =
19462 UA_decodeBinaryInternal(src: buffer, offset: &initial_offset, dst: &hdr,
19463 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], NULL);
19464 UA_assert(res == UA_STATUSCODE_GOOD);
19465 (void)res; /* pacify compilers if assert is ignored */
19466 UA_MessageType msgType = (UA_MessageType)
19467 (hdr.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE);
19468 UA_ChunkType chunkType = (UA_ChunkType)
19469 (hdr.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE);
19470
19471 /* The message size is not allowed */
19472 if(hdr.messageSize < UA_SECURECHANNEL_MESSAGE_MIN_LENGTH)
19473 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19474 if(hdr.messageSize > channel->config.recvBufferSize)
19475 return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
19476
19477 /* Incomplete chunk */
19478 if(hdr.messageSize > remaining) {
19479 *done = true;
19480 return UA_STATUSCODE_GOOD;
19481 }
19482
19483 /* ByteString with only this chunk. */
19484 UA_ByteString chunkPayload;
19485 chunkPayload.data = &buffer->data[*offset];
19486 chunkPayload.length = hdr.messageSize;
19487
19488 if(msgType == UA_MESSAGETYPE_HEL || msgType == UA_MESSAGETYPE_ACK ||
19489 msgType == UA_MESSAGETYPE_ERR || msgType == UA_MESSAGETYPE_OPN) {
19490 if(chunkType != UA_CHUNKTYPE_FINAL)
19491 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19492 } else {
19493 /* Only messages on SecureChannel-level with symmetric encryption afterwards */
19494 if(msgType != UA_MESSAGETYPE_MSG &&
19495 msgType != UA_MESSAGETYPE_CLO)
19496 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19497
19498 /* Check the chunk type before decrypting */
19499 if(chunkType != UA_CHUNKTYPE_FINAL &&
19500 chunkType != UA_CHUNKTYPE_INTERMEDIATE &&
19501 chunkType != UA_CHUNKTYPE_ABORT)
19502 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19503 }
19504
19505 /* Add the chunk; forward the offset */
19506 *offset += hdr.messageSize;
19507 UA_Chunk *chunk = (UA_Chunk*)UA_malloc(size: sizeof(UA_Chunk));
19508 UA_CHECK_MEM(chunk, return UA_STATUSCODE_BADOUTOFMEMORY);
19509
19510 chunk->bytes = chunkPayload;
19511 chunk->messageType = msgType;
19512 chunk->chunkType = chunkType;
19513 chunk->requestId = 0;
19514 chunk->copied = false;
19515
19516 SIMPLEQ_INSERT_TAIL(&channel->completeChunks, chunk, pointers);
19517 return UA_STATUSCODE_GOOD;
19518}
19519
19520UA_StatusCode
19521UA_SecureChannel_processBuffer(UA_SecureChannel *channel, void *application,
19522 UA_ProcessMessageCallback callback,
19523 const UA_ByteString *buffer) {
19524 /* Prepend the incomplete last chunk. This is usually done in the
19525 * networklayer. But we test for a buffered incomplete chunk here again to
19526 * work around "lazy" network layers. */
19527 UA_ByteString appended = channel->incompleteChunk;
19528 if(appended.length > 0) {
19529 channel->incompleteChunk = UA_BYTESTRING_NULL;
19530 UA_Byte *t = (UA_Byte*)UA_realloc(ptr: appended.data, size: appended.length + buffer->length);
19531 UA_CHECK_MEM(t, UA_ByteString_clear(&appended);
19532 return UA_STATUSCODE_BADOUTOFMEMORY);
19533 memcpy(dest: &t[appended.length], src: buffer->data, n: buffer->length);
19534 appended.data = t;
19535 appended.length += buffer->length;
19536 buffer = &appended;
19537 }
19538
19539 /* Loop over the received chunks */
19540 size_t offset = 0;
19541 UA_Boolean done = false;
19542 UA_StatusCode res;
19543 while(!done) {
19544 res = extractCompleteChunk(channel, buffer, offset: &offset, done: &done);
19545 UA_CHECK_STATUS(res, goto cleanup);
19546 }
19547
19548 /* Buffer half-received chunk. Before processing the messages so that
19549 * processing is reentrant. */
19550 if(offset < buffer->length) {
19551 res = persistIncompleteChunk(channel, buffer, offset);
19552 UA_CHECK_STATUS(res, goto cleanup);
19553 }
19554
19555 /* Process whatever we can. Chunks of completed and processed messages are
19556 * removed. */
19557 res = processChunks(channel, application, callback);
19558 UA_CHECK_STATUS(res, goto cleanup);
19559
19560 /* Persist full chunks that still point to the buffer. Can only return
19561 * UA_STATUSCODE_BADOUTOFMEMORY as an error code. So merging res works. */
19562 res |= persistCompleteChunks(queue: &channel->completeChunks);
19563 res |= persistCompleteChunks(queue: &channel->decryptedChunks);
19564
19565 cleanup:
19566 UA_ByteString_clear(p: &appended);
19567 return res;
19568}
19569
19570UA_StatusCode
19571UA_SecureChannel_receive(UA_SecureChannel *channel, void *application,
19572 UA_ProcessMessageCallback callback, UA_UInt32 timeout) {
19573 UA_Connection *connection = channel->connection;
19574 UA_CHECK_MEM(connection, return UA_STATUSCODE_BADINTERNALERROR);
19575
19576 /* Listen for messages to arrive */
19577 UA_ByteString buffer = UA_BYTESTRING_NULL;
19578 UA_StatusCode res = connection->recv(connection, &buffer, timeout);
19579 UA_CHECK_STATUS(res, return res);
19580
19581 /* Try to process one complete chunk */
19582 res = UA_SecureChannel_processBuffer(channel, application, callback, buffer: &buffer);
19583 connection->releaseRecvBuffer(connection, &buffer);
19584 return res;
19585}
19586
19587/**** amalgamated original file "/src/ua_securechannel_crypto.c" ****/
19588
19589/* This Source Code Form is subject to the terms of the Mozilla Public
19590 * License, v. 2.0. If a copy of the MPL was not distributed with this
19591 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
19592 *
19593 * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
19594 * Copyright 2014, 2016-2017 (c) Florian Palm
19595 * Copyright 2015-2016 (c) Sten Grüner
19596 * Copyright 2015 (c) Oleksiy Vasylyev
19597 * Copyright 2016 (c) TorbenD
19598 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
19599 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
19600 */
19601
19602
19603
19604UA_StatusCode
19605UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel) {
19606 const UA_SecurityPolicy *sp = channel->securityPolicy;
19607 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19608 UA_LOG_DEBUG_CHANNEL(sp->logger, channel, "Generating new local nonce");
19609
19610 /* Is the length of the previous nonce correct? */
19611 size_t nonceLength = sp->symmetricModule.secureChannelNonceLength;
19612 if(channel->localNonce.length != nonceLength) {
19613 UA_ByteString_clear(p: &channel->localNonce);
19614 UA_StatusCode res = UA_ByteString_allocBuffer(bs: &channel->localNonce, length: nonceLength);
19615 UA_CHECK_STATUS(res, return res);
19616 }
19617
19618 /* Generate the nonce */
19619 return sp->symmetricModule.generateNonce(sp->policyContext, &channel->localNonce);
19620}
19621
19622UA_StatusCode
19623UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel) {
19624 const UA_SecurityPolicy *sp = channel->securityPolicy;
19625 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19626 UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Generating new local keys");
19627
19628 void *cc = channel->channelContext;
19629 const UA_SecurityPolicyChannelModule *cm = &sp->channelModule;
19630 const UA_SecurityPolicySymmetricModule *sm = &sp->symmetricModule;
19631 const UA_SecurityPolicyCryptoModule *crm = &sm->cryptoModule;
19632
19633 /* Generate symmetric key buffer of the required length. The block size is
19634 * identical for local/remote. */
19635 UA_ByteString buf;
19636 size_t encrKL = crm->encryptionAlgorithm.getLocalKeyLength(cc);
19637 size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(cc);
19638 size_t signKL = crm->signatureAlgorithm.getLocalKeyLength(cc);
19639 if(encrBS + signKL + encrKL == 0)
19640 return UA_STATUSCODE_GOOD; /* No keys to generate */
19641
19642 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &buf, length: encrBS + signKL + encrKL);
19643 UA_CHECK_STATUS(retval, return retval);
19644 UA_ByteString localSigningKey = {signKL, buf.data};
19645 UA_ByteString localEncryptingKey = {encrKL, &buf.data[signKL]};
19646 UA_ByteString localIv = {encrBS, &buf.data[signKL + encrKL]};
19647
19648 /* Generate key */
19649 retval = sm->generateKey(sp->policyContext, &channel->remoteNonce,
19650 &channel->localNonce, &buf);
19651 UA_CHECK_STATUS(retval, goto error);
19652
19653 /* Set the channel context */
19654 retval |= cm->setLocalSymSigningKey(cc, &localSigningKey);
19655 retval |= cm->setLocalSymEncryptingKey(cc, &localEncryptingKey);
19656 retval |= cm->setLocalSymIv(cc, &localIv);
19657
19658 error:
19659 UA_CHECK_STATUS(retval, UA_LOG_WARNING_CHANNEL(sp->logger, channel,
19660 "Could not generate local keys (statuscode: %s)",
19661 UA_StatusCode_name(retval)));
19662 UA_ByteString_clear(p: &buf);
19663 return retval;
19664}
19665
19666UA_StatusCode
19667generateRemoteKeys(const UA_SecureChannel *channel) {
19668 const UA_SecurityPolicy *sp = channel->securityPolicy;
19669 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19670 UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Generating new remote keys");
19671
19672 void *cc = channel->channelContext;
19673 const UA_SecurityPolicyChannelModule *cm = &sp->channelModule;
19674 const UA_SecurityPolicySymmetricModule *sm = &sp->symmetricModule;
19675 const UA_SecurityPolicyCryptoModule *crm = &sm->cryptoModule;
19676
19677 /* Generate symmetric key buffer of the required length */
19678 UA_ByteString buf;
19679 size_t encrKL = crm->encryptionAlgorithm.getRemoteKeyLength(cc);
19680 size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(cc);
19681 size_t signKL = crm->signatureAlgorithm.getRemoteKeyLength(cc);
19682 if(encrBS + signKL + encrKL == 0)
19683 return UA_STATUSCODE_GOOD; /* No keys to generate */
19684
19685 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &buf, length: encrBS + signKL + encrKL);
19686 UA_CHECK_STATUS(retval, return retval);
19687 UA_ByteString remoteSigningKey = {signKL, buf.data};
19688 UA_ByteString remoteEncryptingKey = {encrKL, &buf.data[signKL]};
19689 UA_ByteString remoteIv = {encrBS, &buf.data[signKL + encrKL]};
19690
19691 /* Generate key */
19692 retval = sm->generateKey(sp->policyContext, &channel->localNonce,
19693 &channel->remoteNonce, &buf);
19694 UA_CHECK_STATUS(retval, goto error);
19695
19696 /* Set the channel context */
19697 retval |= cm->setRemoteSymSigningKey(cc, &remoteSigningKey);
19698 retval |= cm->setRemoteSymEncryptingKey(cc, &remoteEncryptingKey);
19699 retval |= cm->setRemoteSymIv(cc, &remoteIv);
19700
19701 error:
19702 UA_CHECK_STATUS(retval, UA_LOG_WARNING_CHANNEL(sp->logger, channel,
19703 "Could not generate remote keys (statuscode: %s)",
19704 UA_StatusCode_name(retval)));
19705 UA_ByteString_clear(p: &buf);
19706 return retval;
19707}
19708
19709/***************************/
19710/* Send Asymmetric Message */
19711/***************************/
19712
19713/* The length of the static header content */
19714#define UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH 12
19715
19716size_t
19717calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
19718 const UA_SecurityPolicy *sp = channel->securityPolicy;
19719 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19720
19721 size_t asymHeaderLength = UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH +
19722 sp->policyUri.length;
19723 if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
19724 return asymHeaderLength;
19725
19726 /* OPN is always encrypted even if the mode is sign only */
19727 asymHeaderLength += 20; /* Thumbprints are always 20 byte long */
19728 asymHeaderLength += sp->localCertificate.length;
19729 return asymHeaderLength;
19730}
19731
19732UA_StatusCode
19733prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
19734 const UA_Byte *buf_end, size_t totalLength,
19735 size_t securityHeaderLength, UA_UInt32 requestId,
19736 size_t *const encryptedLength) {
19737 const UA_SecurityPolicy *sp = channel->securityPolicy;
19738 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19739
19740 if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) {
19741 *encryptedLength = totalLength;
19742 } else {
19743 size_t dataToEncryptLength = totalLength -
19744 (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength);
19745 size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
19746 encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
19747 size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
19748 encryptionAlgorithm.getRemoteBlockSize(channel->channelContext);
19749
19750 /* Padding always fills up the last block */
19751 UA_assert(dataToEncryptLength % plainTextBlockSize == 0);
19752 size_t blocks = dataToEncryptLength / plainTextBlockSize;
19753 *encryptedLength = totalLength + blocks * (encryptedBlockSize - plainTextBlockSize);
19754 }
19755
19756 UA_TcpMessageHeader messageHeader;
19757 messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
19758 messageHeader.messageSize = (UA_UInt32)*encryptedLength;
19759 UA_UInt32 secureChannelId = channel->securityToken.channelId;
19760 UA_StatusCode retval = UA_STATUSCODE_GOOD;
19761 retval |= UA_encodeBinaryInternal(src: &messageHeader,
19762 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
19763 bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL);
19764 retval |= UA_UInt32_encodeBinary(src: &secureChannelId, bufPos: &header_pos, bufEnd: buf_end);
19765 UA_CHECK_STATUS(retval, return retval);
19766
19767 UA_AsymmetricAlgorithmSecurityHeader asymHeader;
19768 UA_AsymmetricAlgorithmSecurityHeader_init(p: &asymHeader);
19769 asymHeader.securityPolicyUri = sp->policyUri;
19770 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
19771 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
19772 asymHeader.senderCertificate = sp->localCertificate;
19773 asymHeader.receiverCertificateThumbprint.length = 20;
19774 asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint;
19775 }
19776 retval = UA_encodeBinaryInternal(src: &asymHeader,
19777 type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
19778 bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL);
19779 UA_CHECK_STATUS(retval, return retval);
19780
19781 UA_SequenceHeader seqHeader;
19782 seqHeader.requestId = requestId;
19783 seqHeader.sequenceNumber = UA_atomic_addUInt32(addr: &channel->sendSequenceNumber, increase: 1);
19784 retval = UA_encodeBinaryInternal(src: &seqHeader, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
19785 bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL);
19786 return retval;
19787}
19788
19789void
19790hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
19791 const UA_Byte **buf_end) {
19792 /* Set buf_start to the beginning of the payload body */
19793 *buf_start += UA_SECURECHANNEL_CHANNELHEADER_LENGTH;
19794 *buf_start += calculateAsymAlgSecurityHeaderLength(channel);
19795 *buf_start += UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
19796
19797#ifdef UA_ENABLE_ENCRYPTION
19798 if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
19799 return;
19800
19801 /* Make space for the certificate */
19802 const UA_SecurityPolicy *sp = channel->securityPolicy;
19803 *buf_end -= sp->asymmetricModule.cryptoModule.signatureAlgorithm.
19804 getLocalSignatureSize(channel->channelContext);
19805
19806 /* Block sizes depend on the remote key (certificate) */
19807 size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
19808 encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
19809 size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
19810 encryptionAlgorithm.getRemoteBlockSize(channel->channelContext);
19811 UA_Boolean extraPadding = (sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
19812 getRemoteKeyLength(channel->channelContext) > 2048);
19813
19814 /* Compute the maximum number of encrypted blocks that can fit entirely
19815 * before the signature. From that compute the maximum usable plaintext
19816 * size. */
19817 size_t maxEncrypted = (size_t)(*buf_end - *buf_start) +
19818 UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
19819 size_t max_blocks = maxEncrypted / encryptedBlockSize;
19820 size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u;
19821 *buf_end = *buf_start + (max_blocks * plainTextBlockSize) -
19822 UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH - paddingBytes;
19823#endif
19824}
19825
19826#ifdef UA_ENABLE_ENCRYPTION
19827
19828/* Assumes that pos can be advanced to the end of the current block */
19829void
19830padChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cm,
19831 const UA_Byte *start, UA_Byte **pos) {
19832 const size_t bytesToWrite = (uintptr_t)*pos - (uintptr_t)start;
19833 size_t signatureSize = cm->signatureAlgorithm.
19834 getLocalSignatureSize(channel->channelContext);
19835 size_t plainTextBlockSize = cm->encryptionAlgorithm.
19836 getRemotePlainTextBlockSize(channel->channelContext);
19837 UA_Boolean extraPadding = (cm->encryptionAlgorithm.
19838 getRemoteKeyLength(channel->channelContext) > 2048);
19839 size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u;
19840
19841 size_t lastBlock = ((bytesToWrite + signatureSize + paddingBytes) % plainTextBlockSize);
19842 size_t paddingLength = (lastBlock != 0) ? plainTextBlockSize - lastBlock : 0;
19843
19844 UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
19845 "Add %lu bytes of padding plus %lu padding size bytes",
19846 (long unsigned int)paddingLength,
19847 (long unsigned int)paddingBytes);
19848
19849 /* Write the padding. This is <= because the paddingSize byte also has to be
19850 * written */
19851 UA_Byte paddingByte = (UA_Byte)paddingLength;
19852 for(UA_UInt16 i = 0; i <= paddingLength; ++i) {
19853 **pos = paddingByte;
19854 ++*pos;
19855 }
19856
19857 /* Write the extra padding byte if required */
19858 if(extraPadding) {
19859 **pos = (UA_Byte)(paddingLength >> 8u);
19860 ++*pos;
19861 }
19862}
19863
19864UA_StatusCode
19865signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength,
19866 UA_ByteString *buf, size_t securityHeaderLength,
19867 size_t totalLength) {
19868 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
19869 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
19870 return UA_STATUSCODE_GOOD;
19871
19872 /* Sign message */
19873 const UA_SecurityPolicy *sp = channel->securityPolicy;
19874 const UA_ByteString dataToSign = {preSignLength, buf->data};
19875 size_t sigsize = sp->asymmetricModule.cryptoModule.signatureAlgorithm.
19876 getLocalSignatureSize(channel->channelContext);
19877 UA_ByteString signature = {sigsize, buf->data + preSignLength};
19878 UA_StatusCode retval = sp->asymmetricModule.cryptoModule.signatureAlgorithm.
19879 sign(channel->channelContext, &dataToSign, &signature);
19880 UA_CHECK_STATUS(retval, return retval);
19881
19882 /* Specification part 6, 6.7.4: The OpenSecureChannel Messages are
19883 * signed and encrypted if the SecurityMode is not None (even if the
19884 * SecurityMode is SignOnly). */
19885 size_t unencrypted_length =
19886 UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength;
19887 UA_ByteString dataToEncrypt = {totalLength - unencrypted_length,
19888 &buf->data[unencrypted_length]};
19889 return sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
19890 encrypt(channel->channelContext, &dataToEncrypt);
19891}
19892
19893/**************************/
19894/* Send Symmetric Message */
19895/**************************/
19896
19897UA_StatusCode
19898signAndEncryptSym(UA_MessageContext *messageContext,
19899 size_t preSigLength, size_t totalLength) {
19900 const UA_SecureChannel *channel = messageContext->channel;
19901 if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
19902 return UA_STATUSCODE_GOOD;
19903
19904 /* Sign */
19905 const UA_SecurityPolicy *sp = channel->securityPolicy;
19906 UA_ByteString dataToSign = messageContext->messageBuffer;
19907 dataToSign.length = preSigLength;
19908 UA_ByteString signature;
19909 signature.length = sp->symmetricModule.cryptoModule.signatureAlgorithm.
19910 getLocalSignatureSize(channel->channelContext);
19911 signature.data = messageContext->buf_pos;
19912 UA_StatusCode res = sp->symmetricModule.cryptoModule.signatureAlgorithm.
19913 sign(channel->channelContext, &dataToSign, &signature);
19914 UA_CHECK_STATUS(res, return res);
19915
19916 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
19917 return UA_STATUSCODE_GOOD;
19918
19919 /* Encrypt */
19920 UA_ByteString dataToEncrypt;
19921 dataToEncrypt.data = messageContext->messageBuffer.data +
19922 UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
19923 UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
19924 dataToEncrypt.length = totalLength -
19925 (UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
19926 UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH);
19927 return sp->symmetricModule.cryptoModule.encryptionAlgorithm.
19928 encrypt(channel->channelContext, &dataToEncrypt);
19929}
19930
19931#endif /* UA_ENABLE_ENCRYPTION */
19932
19933void
19934setBufPos(UA_MessageContext *mc) {
19935 /* Forward the data pointer so that the payload is encoded after the message
19936 * header. This has to be a symmetric message because OPN (with asymmetric
19937 * encryption) does not support chunking. */
19938 mc->buf_pos = &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
19939 mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.length];
19940
19941#ifdef UA_ENABLE_ENCRYPTION
19942 if(mc->channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
19943 return;
19944
19945 const UA_SecureChannel *channel = mc->channel;
19946 const UA_SecurityPolicy *sp = channel->securityPolicy;
19947 size_t sigsize = sp->symmetricModule.cryptoModule.signatureAlgorithm.
19948 getLocalSignatureSize(channel->channelContext);
19949 size_t plainBlockSize = sp->symmetricModule.cryptoModule.
19950 encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
19951
19952 /* Assuming that for symmetric encryption the plainTextBlockSize ==
19953 * cypherTextBlockSize. For symmetric encryption the remote/local block
19954 * sizes are identical. */
19955 UA_assert(sp->symmetricModule.cryptoModule.encryptionAlgorithm.
19956 getRemoteBlockSize(channel->channelContext) == plainBlockSize);
19957
19958 /* Leave enough space for the signature and padding */
19959 mc->buf_end -= sigsize;
19960 mc->buf_end -= mc->messageBuffer.length % plainBlockSize;
19961
19962 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
19963 /* Reserve space for the padding bytes */
19964 UA_Boolean extraPadding =
19965 (sp->symmetricModule.cryptoModule.encryptionAlgorithm.
19966 getRemoteKeyLength(channel->channelContext) > 2048);
19967 mc->buf_end -= (UA_LIKELY(!extraPadding)) ? 1 : 2;
19968 }
19969
19970 UA_LOG_TRACE_CHANNEL(sp->logger, channel,
19971 "Prepare a symmetric message buffer of length %lu "
19972 "with a usable maximum payload length of %lu",
19973 (long unsigned)mc->messageBuffer.length,
19974 (long unsigned)((uintptr_t)mc->buf_end -
19975 (uintptr_t)mc->messageBuffer.data));
19976#endif
19977}
19978
19979/****************************/
19980/* Process a received Chunk */
19981/****************************/
19982
19983static size_t
19984decodePadding(const UA_SecureChannel *channel,
19985 const UA_SecurityPolicyCryptoModule *cryptoModule,
19986 const UA_ByteString *chunk, size_t sigsize) {
19987 /* Read the byte with the padding size */
19988 size_t paddingSize = chunk->data[chunk->length - sigsize - 1];
19989
19990 /* Extra padding size */
19991 if(cryptoModule->encryptionAlgorithm.
19992 getLocalKeyLength(channel->channelContext) > 2048) {
19993 paddingSize <<= 8u;
19994 paddingSize += chunk->data[chunk->length - sigsize - 2];
19995 paddingSize += 1; /* Extra padding byte itself */
19996 }
19997
19998 /* Add one since the paddingSize byte itself needs to be removed as well */
19999 return paddingSize + 1;
20000}
20001
20002static UA_StatusCode
20003verifySignature(const UA_SecureChannel *channel,
20004 const UA_SecurityPolicyCryptoModule *cryptoModule,
20005 const UA_ByteString *chunk, size_t sigsize) {
20006 UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
20007 "Verifying chunk signature");
20008 UA_CHECK(sigsize < chunk->length, return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
20009 const UA_ByteString content = {chunk->length - sigsize, chunk->data};
20010 const UA_ByteString sig = {sigsize, chunk->data + chunk->length - sigsize};
20011 UA_StatusCode retval = cryptoModule->signatureAlgorithm.
20012 verify(channel->channelContext, &content, &sig);
20013#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
20014 retval |= decrypt_verifySignatureFailure;
20015#endif
20016 return retval;
20017}
20018
20019/* Sets the payload to a pointer inside the chunk buffer. Returns the requestId
20020 * and the sequenceNumber */
20021UA_StatusCode
20022decryptAndVerifyChunk(const UA_SecureChannel *channel,
20023 const UA_SecurityPolicyCryptoModule *cryptoModule,
20024 UA_MessageType messageType, UA_ByteString *chunk,
20025 size_t offset) {
20026 /* Decrypt the chunk */
20027 UA_StatusCode res = UA_STATUSCODE_GOOD;
20028 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
20029 messageType == UA_MESSAGETYPE_OPN) {
20030 UA_ByteString cipher = {chunk->length - offset, chunk->data + offset};
20031 res = cryptoModule->encryptionAlgorithm.decrypt(channel->channelContext, &cipher);
20032 UA_CHECK_STATUS(res, return res);
20033 chunk->length = cipher.length + offset;
20034 }
20035
20036 /* Does the message have a signature? */
20037 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
20038 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT &&
20039 messageType != UA_MESSAGETYPE_OPN)
20040 return UA_STATUSCODE_GOOD;
20041
20042 /* Verify the chunk signature */
20043 size_t sigsize = cryptoModule->signatureAlgorithm.
20044 getRemoteSignatureSize(channel->channelContext);
20045 res = verifySignature(channel, cryptoModule, chunk, sigsize);
20046 UA_CHECK_STATUS(res,
20047 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20048 "Could not verify the signature"); return res);
20049
20050 /* Compute the padding if the payload as encrypted */
20051 size_t padSize = 0;
20052 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
20053 (messageType == UA_MESSAGETYPE_OPN &&
20054 cryptoModule->encryptionAlgorithm.uri.length > 0)) {
20055 padSize = decodePadding(channel, cryptoModule, chunk, sigsize);
20056 UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
20057 "Calculated padding size to be %lu",
20058 (long unsigned)padSize);
20059 }
20060
20061 /* Verify the content length. The encrypted payload has to be at least 9
20062 * bytes long: 8 byte for the SequenceHeader and one byte for the actual
20063 * message */
20064 UA_CHECK(offset + padSize + sigsize + 9 < chunk->length,
20065 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20066 "Impossible padding value");
20067 return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
20068
20069 /* Hide the signature and padding */
20070 chunk->length -= (sigsize + padSize);
20071 return UA_STATUSCODE_GOOD;
20072}
20073
20074UA_StatusCode
20075checkAsymHeader(UA_SecureChannel *channel,
20076 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
20077 const UA_SecurityPolicy *sp = channel->securityPolicy;
20078 if(!UA_ByteString_equal(string1: &sp->policyUri, string2: &asymHeader->securityPolicyUri))
20079 return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
20080
20081 return sp->asymmetricModule.
20082 compareCertificateThumbprint(sp, &asymHeader->receiverCertificateThumbprint);
20083
20084 /* The certificate in the header is verified via the configured PKI plugin
20085 * as certificateVerification.verifyCertificate(...). We cannot do it here
20086 * because the client/server context is needed. */
20087}
20088
20089UA_StatusCode
20090checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId) {
20091 /* If no match, try to revolve to the next token after a
20092 * RenewSecureChannel */
20093 UA_StatusCode retval = UA_STATUSCODE_GOOD;
20094 UA_ChannelSecurityToken *token = &channel->securityToken;
20095 switch(channel->renewState) {
20096 case UA_SECURECHANNELRENEWSTATE_NORMAL:
20097 case UA_SECURECHANNELRENEWSTATE_SENT:
20098 default:
20099 break;
20100
20101 case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER:
20102 /* Old token still in use */
20103 if(tokenId == channel->securityToken.tokenId)
20104 break;
20105
20106 /* Not the new token */
20107 UA_CHECK(tokenId == channel->altSecurityToken.tokenId,
20108 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20109 "Unknown SecurityToken");
20110 return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
20111
20112 /* Roll over to the new token, generate new local and remote keys */
20113 channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
20114 channel->securityToken = channel->altSecurityToken;
20115 UA_ChannelSecurityToken_init(p: &channel->altSecurityToken);
20116 retval |= UA_SecureChannel_generateLocalKeys(channel);
20117 retval |= generateRemoteKeys(channel);
20118 UA_CHECK_STATUS(retval, return retval);
20119 break;
20120
20121 case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT:
20122 /* The server is still using the old token. That's okay. */
20123 if(tokenId == channel->altSecurityToken.tokenId) {
20124 token = &channel->altSecurityToken;
20125 break;
20126 }
20127
20128 /* Not the new token */
20129 UA_CHECK(tokenId == channel->securityToken.tokenId,
20130 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20131 "Unknown SecurityToken");
20132 return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
20133
20134 /* The remote server uses the new token for the first time. Delete the
20135 * old token and roll the remote key over. The local key already uses
20136 * the nonce pair from the last OPN exchange. */
20137 channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
20138 UA_ChannelSecurityToken_init(p: &channel->altSecurityToken);
20139 retval = generateRemoteKeys(channel);
20140 UA_CHECK_STATUS(retval, return retval);
20141 }
20142
20143 UA_DateTime timeout = token->createdAt + (token->revisedLifetime * UA_DATETIME_MSEC);
20144 if(channel->state == UA_SECURECHANNELSTATE_OPEN &&
20145 timeout < UA_DateTime_nowMonotonic()) {
20146 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20147 "SecurityToken timed out");
20148 UA_SecureChannel_close(channel);
20149 return UA_STATUSCODE_BADSECURECHANNELCLOSED;
20150 }
20151
20152 return UA_STATUSCODE_GOOD;
20153}
20154
20155/**** amalgamated original file "/src/server/ua_session.c" ****/
20156
20157/* This Source Code Form is subject to the terms of the Mozilla Public
20158 * License, v. 2.0. If a copy of the MPL was not distributed with this
20159 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
20160 *
20161 * Copyright 2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
20162 * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
20163 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
20164 */
20165
20166#ifdef UA_ENABLE_SUBSCRIPTIONS
20167#endif
20168
20169#define UA_SESSION_NONCELENTH 32
20170
20171void UA_Session_init(UA_Session *session) {
20172 memset(s: session, c: 0, n: sizeof(UA_Session));
20173 session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
20174#ifdef UA_ENABLE_SUBSCRIPTIONS
20175 SIMPLEQ_INIT(&session->responseQueue);
20176 TAILQ_INIT(&session->subscriptions);
20177#endif
20178}
20179
20180void UA_Session_clear(UA_Session *session, UA_Server* server) {
20181 UA_LOCK_ASSERT(&server->serviceMutex, 1);
20182
20183 /* Remove all Subscriptions. This may send out remaining publish
20184 * responses. */
20185#ifdef UA_ENABLE_SUBSCRIPTIONS
20186 UA_Subscription *sub, *tempsub;
20187 TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) {
20188 UA_Subscription_delete(server, sub);
20189 }
20190#endif
20191
20192#ifdef UA_ENABLE_DIAGNOSTICS
20193 deleteNode(server, session->sessionId, true);
20194#endif
20195
20196 UA_Session_detachFromSecureChannel(session);
20197 UA_ApplicationDescription_clear(p: &session->clientDescription);
20198 UA_NodeId_clear(p: &session->header.authenticationToken);
20199 UA_NodeId_clear(p: &session->sessionId);
20200 UA_String_clear(p: &session->sessionName);
20201 UA_ByteString_clear(p: &session->serverNonce);
20202 struct ContinuationPoint *cp, *next = session->continuationPoints;
20203 while((cp = next)) {
20204 next = ContinuationPoint_clear(cp);
20205 UA_free(ptr: cp);
20206 }
20207 session->continuationPoints = NULL;
20208 session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
20209
20210 UA_Array_delete(p: session->params, size: session->paramsSize,
20211 type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
20212 session->params = NULL;
20213 session->paramsSize = 0;
20214
20215 UA_Array_delete(p: session->localeIds, size: session->localeIdsSize,
20216 type: &UA_TYPES[UA_TYPES_STRING]);
20217 session->localeIds = NULL;
20218 session->localeIdsSize = 0;
20219
20220#ifdef UA_ENABLE_DIAGNOSTICS
20221 UA_SessionDiagnosticsDataType_clear(&session->diagnostics);
20222 UA_SessionSecurityDiagnosticsDataType_clear(&session->securityDiagnostics);
20223#endif
20224}
20225
20226void
20227UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel) {
20228 UA_Session_detachFromSecureChannel(session);
20229 session->header.channel = channel;
20230 session->header.serverSession = true;
20231 SLIST_INSERT_HEAD(&channel->sessions, &session->header, next);
20232}
20233
20234void
20235UA_Session_detachFromSecureChannel(UA_Session *session) {
20236 UA_SecureChannel *channel = session->header.channel;
20237 if(!channel)
20238 return;
20239 session->header.channel = NULL;
20240 UA_SessionHeader *sh;
20241 SLIST_FOREACH(sh, &channel->sessions, next) {
20242 if((UA_Session*)sh != session)
20243 continue;
20244 SLIST_REMOVE(&channel->sessions, sh, UA_SessionHeader, next);
20245 break;
20246 }
20247
20248 /* Clean up the response queue. Their RequestId is bound to the
20249 * SecureChannel so they cannot be reused. */
20250#ifdef UA_ENABLE_SUBSCRIPTIONS
20251 UA_PublishResponseEntry *pre;
20252 while((pre = UA_Session_dequeuePublishReq(session))) {
20253 UA_PublishResponse_clear(p: &pre->response);
20254 UA_free(ptr: pre);
20255 }
20256#endif
20257}
20258
20259UA_StatusCode
20260UA_Session_generateNonce(UA_Session *session) {
20261 UA_SecureChannel *channel = session->header.channel;
20262 if(!channel || !channel->securityPolicy)
20263 return UA_STATUSCODE_BADINTERNALERROR;
20264
20265 /* Is the length of the previous nonce correct? */
20266 if(session->serverNonce.length != UA_SESSION_NONCELENTH) {
20267 UA_ByteString_clear(p: &session->serverNonce);
20268 UA_StatusCode retval =
20269 UA_ByteString_allocBuffer(bs: &session->serverNonce, UA_SESSION_NONCELENTH);
20270 if(retval != UA_STATUSCODE_GOOD)
20271 return retval;
20272 }
20273
20274 return channel->securityPolicy->symmetricModule.
20275 generateNonce(channel->securityPolicy->policyContext, &session->serverNonce);
20276}
20277
20278void UA_Session_updateLifetime(UA_Session *session) {
20279 session->validTill = UA_DateTime_nowMonotonic() +
20280 (UA_DateTime)(session->timeout * UA_DATETIME_MSEC);
20281#ifdef UA_ENABLE_DIAGNOSTICS
20282 session->diagnostics.clientLastContactTime = UA_DateTime_now();
20283#endif
20284}
20285
20286#ifdef UA_ENABLE_SUBSCRIPTIONS
20287
20288void
20289UA_Session_attachSubscription(UA_Session *session, UA_Subscription *sub) {
20290 /* Attach to the session */
20291 sub->session = session;
20292
20293 /* Increase the count */
20294 session->subscriptionsSize++;
20295
20296 /* Increase the number of outstanding retransmissions */
20297 session->totalRetransmissionQueueSize += sub->retransmissionQueueSize;
20298
20299 /* Insert at the end of the subscriptions of the same priority / just before
20300 * the subscriptions with the next lower priority. */
20301 UA_Subscription *after = NULL;
20302 TAILQ_FOREACH(after, &session->subscriptions, sessionListEntry) {
20303 if(after->priority < sub->priority) {
20304 TAILQ_INSERT_BEFORE(after, sub, sessionListEntry);
20305 return;
20306 }
20307 }
20308 TAILQ_INSERT_TAIL(&session->subscriptions, sub, sessionListEntry);
20309}
20310
20311void
20312UA_Session_detachSubscription(UA_Server *server, UA_Session *session,
20313 UA_Subscription *sub, UA_Boolean releasePublishResponses) {
20314 /* Detach from the session */
20315 sub->session = NULL;
20316 TAILQ_REMOVE(&session->subscriptions, sub, sessionListEntry);
20317
20318 /* Reduce the count */
20319 UA_assert(session->subscriptionsSize > 0);
20320 session->subscriptionsSize--;
20321
20322 /* Reduce the number of outstanding retransmissions */
20323 session->totalRetransmissionQueueSize -= sub->retransmissionQueueSize;
20324
20325 /* Send remaining publish responses if the last subscription was removed */
20326 if(!releasePublishResponses || !TAILQ_EMPTY(&session->subscriptions))
20327 return;
20328 UA_PublishResponseEntry *pre;
20329 while((pre = UA_Session_dequeuePublishReq(session))) {
20330 UA_PublishResponse *response = &pre->response;
20331 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
20332 response->responseHeader.timestamp = UA_DateTime_now();
20333 sendResponse(server, session, channel: session->header.channel, requestId: pre->requestId,
20334 response: (UA_Response*)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
20335 UA_PublishResponse_clear(p: response);
20336 UA_free(ptr: pre);
20337 }
20338}
20339
20340UA_Subscription *
20341UA_Session_getSubscriptionById(UA_Session *session, UA_UInt32 subscriptionId) {
20342 UA_Subscription *sub;
20343 TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
20344 /* Prevent lookup of subscriptions that are to be deleted with a statuschange */
20345 if(sub->statusChange != UA_STATUSCODE_GOOD)
20346 continue;
20347 if(sub->subscriptionId == subscriptionId)
20348 break;
20349 }
20350 return sub;
20351}
20352
20353UA_Subscription *
20354UA_Server_getSubscriptionById(UA_Server *server, UA_UInt32 subscriptionId) {
20355 UA_Subscription *sub;
20356 LIST_FOREACH(sub, &server->subscriptions, serverListEntry) {
20357 /* Prevent lookup of subscriptions that are to be deleted with a statuschange */
20358 if(sub->statusChange != UA_STATUSCODE_GOOD)
20359 continue;
20360 if(sub->subscriptionId == subscriptionId)
20361 break;
20362 }
20363 return sub;
20364}
20365
20366UA_PublishResponseEntry*
20367UA_Session_dequeuePublishReq(UA_Session *session) {
20368 UA_PublishResponseEntry* entry = SIMPLEQ_FIRST(&session->responseQueue);
20369 if(entry) {
20370 SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry);
20371 session->responseQueueSize--;
20372 }
20373 return entry;
20374}
20375
20376void
20377UA_Session_queuePublishReq(UA_Session *session, UA_PublishResponseEntry* entry,
20378 UA_Boolean head) {
20379 if(!head)
20380 SIMPLEQ_INSERT_TAIL(&session->responseQueue, entry, listEntry);
20381 else
20382 SIMPLEQ_INSERT_HEAD(&session->responseQueue, entry, listEntry);
20383 session->responseQueueSize++;
20384}
20385
20386#endif
20387
20388/* Session Handling */
20389
20390UA_StatusCode
20391UA_Server_closeSession(UA_Server *server, const UA_NodeId *sessionId) {
20392 UA_LOCK(&server->serviceMutex);
20393 session_list_entry *entry;
20394 UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID;
20395 LIST_FOREACH(entry, &server->sessions, pointers) {
20396 if(UA_NodeId_equal(n1: &entry->session.sessionId, n2: sessionId)) {
20397 UA_Server_removeSession(server, sentry: entry, event: UA_DIAGNOSTICEVENT_CLOSE);
20398 res = UA_STATUSCODE_GOOD;
20399 break;
20400 }
20401 }
20402 UA_UNLOCK(&server->serviceMutex);
20403 return res;
20404}
20405
20406UA_StatusCode
20407UA_Server_setSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
20408 const char *name, const UA_Variant *parameter) {
20409 UA_LOCK(&server->serviceMutex);
20410 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20411 UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID;
20412 if(session)
20413 res = UA_KeyValueMap_set(map: &session->params, mapSize: &session->paramsSize,
20414 key: name, value: parameter);
20415 UA_UNLOCK(&server->serviceMutex);
20416 return res;
20417}
20418
20419void
20420UA_Server_deleteSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
20421 const char *name) {
20422 UA_LOCK(&server->serviceMutex);
20423 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20424 if(session)
20425 UA_KeyValueMap_delete(map: &session->params, mapSize: &session->paramsSize, key: name);
20426 UA_UNLOCK(&server->serviceMutex);
20427}
20428
20429UA_StatusCode
20430UA_Server_getSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
20431 const char *name, UA_Variant *outParameter) {
20432 UA_LOCK(&server->serviceMutex);
20433 if(!outParameter) {
20434 UA_UNLOCK(&server->serviceMutex);
20435 return UA_STATUSCODE_BADINTERNALERROR;
20436 }
20437
20438 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20439 if(!session) {
20440 UA_UNLOCK(&server->serviceMutex);
20441 return UA_STATUSCODE_BADSESSIONIDINVALID;
20442 }
20443
20444 const UA_Variant *param =
20445 UA_KeyValueMap_get(map: session->params, mapSize: session->paramsSize, key: name);
20446 if(!param) {
20447 UA_UNLOCK(&server->serviceMutex);
20448 return UA_STATUSCODE_BADNOTFOUND;
20449 }
20450
20451 UA_StatusCode res = UA_Variant_copy(src: param, dst: outParameter);
20452 UA_UNLOCK(&server->serviceMutex);
20453 return res;
20454}
20455
20456UA_StatusCode
20457UA_Server_getSessionScalarParameter(UA_Server *server, const UA_NodeId *sessionId,
20458 const char *name, const UA_DataType *type,
20459 UA_Variant *outParameter) {
20460 UA_LOCK(&server->serviceMutex);
20461 if(!outParameter) {
20462 UA_UNLOCK(&server->serviceMutex);
20463 return UA_STATUSCODE_BADINTERNALERROR;
20464 }
20465
20466 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20467 if(!session) {
20468 UA_UNLOCK(&server->serviceMutex);
20469 return UA_STATUSCODE_BADSESSIONIDINVALID;
20470 }
20471
20472 const UA_Variant *param =
20473 UA_KeyValueMap_get(map: session->params, mapSize: session->paramsSize, key: name);
20474 if(!param || !UA_Variant_hasScalarType(v: param, type)) {
20475 UA_UNLOCK(&server->serviceMutex);
20476 return UA_STATUSCODE_BADNOTFOUND;
20477 }
20478
20479 UA_StatusCode res = UA_Variant_copy(src: param, dst: outParameter);
20480 UA_UNLOCK(&server->serviceMutex);
20481 return res;
20482}
20483
20484UA_StatusCode
20485UA_Server_getSessionArrayParameter(UA_Server *server, const UA_NodeId *sessionId,
20486 const char *name, const UA_DataType *type,
20487 UA_Variant *outParameter) {
20488 UA_LOCK(&server->serviceMutex);
20489 if(!outParameter) {
20490 UA_UNLOCK(&server->serviceMutex);
20491 return UA_STATUSCODE_BADINTERNALERROR;
20492 }
20493
20494 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20495 if(!session) {
20496 UA_UNLOCK(&server->serviceMutex);
20497 return UA_STATUSCODE_BADSESSIONIDINVALID;
20498 }
20499
20500 const UA_Variant *param =
20501 UA_KeyValueMap_get(map: session->params, mapSize: session->paramsSize, key: name);
20502 if(!param || !UA_Variant_hasArrayType(v: param, type)) {
20503 UA_UNLOCK(&server->serviceMutex);
20504 return UA_STATUSCODE_BADNOTFOUND;
20505 }
20506
20507 UA_StatusCode res = UA_Variant_copy(src: param, dst: outParameter);
20508 UA_UNLOCK(&server->serviceMutex);
20509 return res;
20510}
20511
20512/**** amalgamated original file "/src/server/ua_nodes.c" ****/
20513
20514/* This Source Code Form is subject to the terms of the Mozilla Public
20515 * License, v. 2.0. If a copy of the MPL was not distributed with this
20516 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
20517 *
20518 * Copyright 2015-2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
20519 * Copyright 2015-2016 (c) Sten Grüner
20520 * Copyright 2015 (c) Chris Iatrou
20521 * Copyright 2015, 2017 (c) Florian Palm
20522 * Copyright 2015 (c) Oleksiy Vasylyev
20523 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
20524 * Copyright 2017 (c) Julian Grothoff
20525 */
20526
20527
20528/*****************/
20529/* Node Pointers */
20530/*****************/
20531
20532#define UA_NODEPOINTER_MASK 0x03
20533#define UA_NODEPOINTER_TAG_IMMEDIATE 0x00
20534#define UA_NODEPOINTER_TAG_NODEID 0x01
20535#define UA_NODEPOINTER_TAG_EXPANDEDNODEID 0x02
20536#define UA_NODEPOINTER_TAG_NODE 0x03
20537
20538void
20539UA_NodePointer_clear(UA_NodePointer *np) {
20540 switch(np->immediate & UA_NODEPOINTER_MASK) {
20541 case UA_NODEPOINTER_TAG_NODEID:
20542 np->immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20543 UA_NodeId_delete(p: (UA_NodeId*)(uintptr_t)np->id);
20544 break;
20545 case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
20546 np->immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20547 UA_ExpandedNodeId_delete(p: (UA_ExpandedNodeId*)(uintptr_t)
20548 np->expandedId);
20549 break;
20550 default:
20551 break;
20552 }
20553 UA_NodePointer_init(np);
20554}
20555
20556UA_StatusCode
20557UA_NodePointer_copy(UA_NodePointer in, UA_NodePointer *out) {
20558 UA_StatusCode res = UA_STATUSCODE_GOOD;
20559 UA_Byte tag = in.immediate & UA_NODEPOINTER_MASK;
20560 in.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20561 switch(tag) {
20562 case UA_NODEPOINTER_TAG_NODE:
20563 in.id = &in.node->nodeId;
20564 goto nodeid; /* fallthrough */
20565 case UA_NODEPOINTER_TAG_NODEID:
20566 nodeid:
20567 out->id = UA_NodeId_new();
20568 if(!out->id)
20569 return UA_STATUSCODE_BADOUTOFMEMORY;
20570 res = UA_NodeId_copy(src: in.id, dst: (UA_NodeId*)(uintptr_t)out->id);
20571 if(res != UA_STATUSCODE_GOOD) {
20572 UA_free(ptr: (void*)out->immediate);
20573 out->immediate = 0;
20574 break;
20575 }
20576 out->immediate |= UA_NODEPOINTER_TAG_NODEID;
20577 break;
20578 case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
20579 out->expandedId = UA_ExpandedNodeId_new();
20580 if(!out->expandedId)
20581 return UA_STATUSCODE_BADOUTOFMEMORY;
20582 res = UA_ExpandedNodeId_copy(src: in.expandedId,
20583 dst: (UA_ExpandedNodeId*)(uintptr_t)
20584 out->expandedId);
20585 if(res != UA_STATUSCODE_GOOD) {
20586 UA_free(ptr: (void*)out->immediate);
20587 out->immediate = 0;
20588 break;
20589 }
20590 out->immediate |= UA_NODEPOINTER_TAG_EXPANDEDNODEID;
20591 break;
20592 default:
20593 case UA_NODEPOINTER_TAG_IMMEDIATE:
20594 *out = in;
20595 break;
20596 }
20597 return res;
20598}
20599
20600UA_Boolean
20601UA_NodePointer_isLocal(UA_NodePointer np) {
20602 UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
20603 return (tag != UA_NODEPOINTER_TAG_EXPANDEDNODEID);
20604}
20605
20606UA_Order
20607UA_NodePointer_order(UA_NodePointer p1, UA_NodePointer p2) {
20608 if(p1.immediate == p2.immediate)
20609 return UA_ORDER_EQ;
20610
20611 /* Extract the tag and resolve pointers to nodes */
20612 UA_Byte tag1 = p1.immediate & UA_NODEPOINTER_MASK;
20613 if(tag1 == UA_NODEPOINTER_TAG_NODE) {
20614 p1 = UA_NodePointer_fromNodeId(id: &p1.node->nodeId);
20615 tag1 = p1.immediate & UA_NODEPOINTER_MASK;
20616 }
20617 UA_Byte tag2 = p2.immediate & UA_NODEPOINTER_MASK;
20618 if(tag2 == UA_NODEPOINTER_TAG_NODE) {
20619 p2 = UA_NodePointer_fromNodeId(id: &p2.node->nodeId);
20620 tag2 = p2.immediate & UA_NODEPOINTER_MASK;
20621 }
20622
20623 /* Different tags, cannot be identical */
20624 if(tag1 != tag2)
20625 return (tag1 > tag2) ? UA_ORDER_MORE : UA_ORDER_LESS;
20626
20627 /* Immediate */
20628 if(UA_LIKELY(tag1 == UA_NODEPOINTER_TAG_IMMEDIATE))
20629 return (p1.immediate > p2.immediate) ?
20630 UA_ORDER_MORE : UA_ORDER_LESS;
20631
20632 /* Compare from pointers */
20633 p1.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20634 p2.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20635 if(tag1 == UA_NODEPOINTER_TAG_EXPANDEDNODEID)
20636 return UA_ExpandedNodeId_order(n1: p1.expandedId, n2: p2.expandedId);
20637 return UA_NodeId_order(n1: p1.id, n2: p2.id);
20638}
20639
20640UA_NodePointer
20641UA_NodePointer_fromNodeId(const UA_NodeId *id) {
20642 UA_NodePointer np;
20643 if(id->identifierType != UA_NODEIDTYPE_NUMERIC) {
20644 np.id = id;
20645 np.immediate |= UA_NODEPOINTER_TAG_NODEID;
20646 return np;
20647 }
20648
20649#if SIZE_MAX > UA_UINT32_MAX
20650 /* 64bit: 4 Byte for the numeric identifier + 2 Byte for the namespaceIndex
20651 * + 1 Byte for the tagging bit (zero) */
20652 np.immediate = ((uintptr_t)id->identifier.numeric) << 32;
20653 np.immediate |= ((uintptr_t)id->namespaceIndex) << 8;
20654#else
20655 /* 32bit: 3 Byte for the numeric identifier + 6 Bit for the namespaceIndex
20656 * + 2 Bit for the tagging bit (zero) */
20657 if(id->namespaceIndex < (0x01 << 6) &&
20658 id->identifier.numeric < (0x01 << 24)) {
20659 np.immediate = ((uintptr_t)id->identifier.numeric) << 8;
20660 np.immediate |= ((uintptr_t)id->namespaceIndex) << 2;
20661 } else {
20662 np.id = id;
20663 np.immediate |= UA_NODEPOINTER_TAG_NODEID;
20664 }
20665#endif
20666 return np;
20667}
20668
20669UA_NodeId
20670UA_NodePointer_toNodeId(UA_NodePointer np) {
20671 UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
20672 np.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20673 switch(tag) {
20674 case UA_NODEPOINTER_TAG_NODE:
20675 return np.node->nodeId;
20676 case UA_NODEPOINTER_TAG_NODEID:
20677 return *np.id;
20678 case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
20679 return np.expandedId->nodeId;
20680 default:
20681 case UA_NODEPOINTER_TAG_IMMEDIATE:
20682 break;
20683 }
20684
20685 UA_NodeId id;
20686 id.identifierType = UA_NODEIDTYPE_NUMERIC;
20687#if SIZE_MAX > UA_UINT32_MAX /* 64bit */
20688 id.namespaceIndex = (UA_UInt16)(np.immediate >> 8);
20689 id.identifier.numeric = (UA_UInt32)(np.immediate >> 32);
20690#else /* 32bit */
20691 id.namespaceIndex = ((UA_Byte)np.immediate) >> 2;
20692 id.identifier.numeric = np.immediate >> 8;
20693#endif
20694 return id;
20695}
20696
20697UA_NodePointer
20698UA_NodePointer_fromExpandedNodeId(const UA_ExpandedNodeId *id) {
20699 if(!UA_ExpandedNodeId_isLocal(n: id)) {
20700 UA_NodePointer np;
20701 np.expandedId = id;
20702 np.immediate |= UA_NODEPOINTER_TAG_EXPANDEDNODEID;
20703 return np;
20704 }
20705 return UA_NodePointer_fromNodeId(id: &id->nodeId);
20706}
20707
20708UA_ExpandedNodeId
20709UA_NodePointer_toExpandedNodeId(UA_NodePointer np) {
20710 /* Resolve node pointer to get the NodeId */
20711 UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
20712 if(tag == UA_NODEPOINTER_TAG_NODE) {
20713 np = UA_NodePointer_fromNodeId(id: &np.node->nodeId);
20714 tag = np.immediate & UA_NODEPOINTER_MASK;
20715 }
20716
20717 /* ExpandedNodeId, make a shallow copy */
20718 if(tag == UA_NODEPOINTER_TAG_EXPANDEDNODEID) {
20719 np.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20720 return *np.expandedId;
20721 }
20722
20723 /* NodeId, either immediate or via a pointer */
20724 UA_ExpandedNodeId en;
20725 UA_ExpandedNodeId_init(p: &en);
20726 en.nodeId = UA_NodePointer_toNodeId(np);
20727 return en;
20728}
20729
20730/**************/
20731/* References */
20732/**************/
20733
20734static UA_StatusCode
20735addReferenceTarget(UA_NodeReferenceKind *refs, UA_NodePointer target,
20736 UA_UInt32 targetNameHash);
20737
20738static enum aa_cmp
20739cmpRefTargetId(const void *a, const void *b) {
20740 const UA_ReferenceTargetTreeElem *aa = (const UA_ReferenceTargetTreeElem*)a;
20741 const UA_ReferenceTargetTreeElem *bb = (const UA_ReferenceTargetTreeElem*)b;
20742 if(aa->targetIdHash < bb->targetIdHash)
20743 return AA_CMP_LESS;
20744 if(aa->targetIdHash > bb->targetIdHash)
20745 return AA_CMP_MORE;
20746 return (enum aa_cmp)UA_NodePointer_order(p1: aa->target.targetId,
20747 p2: bb->target.targetId);
20748}
20749
20750static enum aa_cmp
20751cmpRefTargetName(const void *a, const void *b) {
20752 const UA_UInt32 *nameHashA = (const UA_UInt32*)a;
20753 const UA_UInt32 *nameHashB = (const UA_UInt32*)b;
20754 if(*nameHashA < *nameHashB)
20755 return AA_CMP_LESS;
20756 if(*nameHashA > *nameHashB)
20757 return AA_CMP_MORE;
20758 return AA_CMP_EQ;
20759}
20760
20761/* Reusable binary search tree "heads". Just switch out the root pointer. */
20762static const struct aa_head refIdTree =
20763 { NULL, cmpRefTargetId, offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
20764const struct aa_head refNameTree =
20765 { NULL, cmpRefTargetName, offsetof(UA_ReferenceTargetTreeElem, nameTreeEntry),
20766 offsetof(UA_ReferenceTarget, targetNameHash) };
20767
20768const UA_ReferenceTarget *
20769UA_NodeReferenceKind_iterate(const UA_NodeReferenceKind *rk,
20770 const UA_ReferenceTarget *prev) {
20771 /* Return from the tree */
20772 if(rk->hasRefTree) {
20773 const struct aa_head _refIdTree =
20774 { rk->targets.tree.idTreeRoot, cmpRefTargetId,
20775 offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
20776 if(prev == NULL)
20777 return (const UA_ReferenceTarget*)aa_min(head: &_refIdTree);
20778 return (const UA_ReferenceTarget*)aa_next(head: &_refIdTree, elem: prev);
20779 }
20780 if(prev == NULL) /* Return start of the array */
20781 return rk->targets.array;
20782 if(prev + 1 >= &rk->targets.array[rk->targetsSize])
20783 return NULL; /* End of the array */
20784 return prev + 1; /* Next element in the array */
20785}
20786
20787/* Also deletes the elements of the tree */
20788static void
20789moveTreeToArray(UA_ReferenceTarget *array, size_t *pos,
20790 struct aa_entry *entry) {
20791 if(!entry)
20792 return;
20793 UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
20794 ((uintptr_t)entry - offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
20795 moveTreeToArray(array, pos, entry: elem->idTreeEntry.left);
20796 moveTreeToArray(array, pos, entry: elem->idTreeEntry.right);
20797 array[*pos] = elem->target;
20798 (*pos)++;
20799 UA_free(ptr: elem);
20800}
20801
20802UA_StatusCode
20803UA_NodeReferenceKind_switch(UA_NodeReferenceKind *rk) {
20804 if(rk->hasRefTree) {
20805 /* From tree to array */
20806 UA_ReferenceTarget *array = (UA_ReferenceTarget*)
20807 UA_malloc(size: sizeof(UA_ReferenceTarget) * rk->targetsSize);
20808 if(!array)
20809 return UA_STATUSCODE_BADOUTOFMEMORY;
20810 size_t pos = 0;
20811 moveTreeToArray(array, pos: &pos, entry: rk->targets.tree.idTreeRoot);
20812 rk->targets.array = array;
20813 rk->hasRefTree = false;
20814 return UA_STATUSCODE_GOOD;
20815 }
20816
20817 /* From array to tree */
20818 UA_NodeReferenceKind newRk = *rk;
20819 newRk.hasRefTree = true;
20820 newRk.targets.tree.idTreeRoot = NULL;
20821 newRk.targets.tree.nameTreeRoot = NULL;
20822 for(size_t i = 0; i < rk->targetsSize; i++) {
20823 UA_StatusCode res =
20824 addReferenceTarget(refs: &newRk, target: rk->targets.array[i].targetId,
20825 targetNameHash: rk->targets.array[i].targetNameHash);
20826 if(res != UA_STATUSCODE_GOOD) {
20827 struct aa_head _refIdTree = refIdTree;
20828 _refIdTree.root = newRk.targets.tree.idTreeRoot;
20829 while(_refIdTree.root) {
20830 UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
20831 ((uintptr_t)_refIdTree.root -
20832 offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
20833 aa_remove(head: &_refIdTree, elem);
20834 UA_NodePointer_clear(np: &elem->target.targetId);
20835 UA_free(ptr: elem);
20836 }
20837 return res;
20838 }
20839 }
20840 for(size_t i = 0; i < rk->targetsSize; i++)
20841 UA_NodePointer_clear(np: &rk->targets.array[i].targetId);
20842 UA_free(ptr: rk->targets.array);
20843 *rk = newRk;
20844 return UA_STATUSCODE_GOOD;
20845}
20846
20847const UA_ReferenceTarget *
20848UA_NodeReferenceKind_findTarget(const UA_NodeReferenceKind *rk,
20849 const UA_ExpandedNodeId *targetId) {
20850 UA_NodePointer targetP = UA_NodePointer_fromExpandedNodeId(id: targetId);
20851
20852 /* Return from the tree */
20853 if(rk->hasRefTree) {
20854 UA_ReferenceTargetTreeElem tmpTarget;
20855 tmpTarget.target.targetId = targetP;
20856 tmpTarget.targetIdHash = UA_ExpandedNodeId_hash(n: targetId);
20857 const struct aa_head _refIdTree =
20858 { rk->targets.tree.idTreeRoot, cmpRefTargetId,
20859 offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
20860 return (const UA_ReferenceTarget*)aa_find(head: &_refIdTree, key: &tmpTarget);
20861 }
20862
20863 /* Return from the array */
20864 for(size_t i = 0; i < rk->targetsSize; i++) {
20865 if(UA_NodePointer_equal(p1: targetP, p2: rk->targets.array[i].targetId))
20866 return &rk->targets.array[i];
20867 }
20868 return NULL;
20869}
20870
20871const UA_Node *
20872UA_NODESTORE_GETFROMREF(UA_Server *server, UA_NodePointer target) {
20873 if(!UA_NodePointer_isLocal(np: target))
20874 return NULL;
20875 UA_NodeId id = UA_NodePointer_toNodeId(np: target);
20876 return UA_NODESTORE_GET(server, &id);
20877}
20878
20879/* General node handling methods. There is no UA_Node_new() method here.
20880 * Creating nodes is part of the Nodestore layer */
20881
20882void UA_Node_clear(UA_Node *node) {
20883 /* Delete references */
20884 UA_Node_deleteReferences(node);
20885
20886 /* Delete other head content */
20887 UA_NodeHead *head = &node->head;
20888 UA_NodeId_clear(p: &head->nodeId);
20889 UA_QualifiedName_clear(p: &head->browseName);
20890 UA_LocalizedText_clear(p: &head->displayName);
20891 UA_LocalizedText_clear(p: &head->description);
20892
20893 /* Delete unique content of the nodeclass */
20894 switch(head->nodeClass) {
20895 case UA_NODECLASS_OBJECT:
20896 break;
20897 case UA_NODECLASS_METHOD:
20898 break;
20899 case UA_NODECLASS_OBJECTTYPE:
20900 break;
20901 case UA_NODECLASS_VARIABLE:
20902 case UA_NODECLASS_VARIABLETYPE: {
20903 UA_VariableNode *p = &node->variableNode;
20904 UA_NodeId_clear(p: &p->dataType);
20905 UA_Array_delete(p: p->arrayDimensions, size: p->arrayDimensionsSize,
20906 type: &UA_TYPES[UA_TYPES_INT32]);
20907 p->arrayDimensions = NULL;
20908 p->arrayDimensionsSize = 0;
20909 if(p->valueSource == UA_VALUESOURCE_DATA)
20910 UA_DataValue_clear(p: &p->value.data.value);
20911 break;
20912 }
20913 case UA_NODECLASS_REFERENCETYPE: {
20914 UA_ReferenceTypeNode *p = &node->referenceTypeNode;
20915 UA_LocalizedText_clear(p: &p->inverseName);
20916 break;
20917 }
20918 case UA_NODECLASS_DATATYPE:
20919 break;
20920 case UA_NODECLASS_VIEW:
20921 break;
20922 default:
20923 break;
20924 }
20925}
20926
20927static UA_StatusCode
20928UA_ObjectNode_copy(const UA_ObjectNode *src, UA_ObjectNode *dst) {
20929 dst->eventNotifier = src->eventNotifier;
20930 return UA_STATUSCODE_GOOD;
20931}
20932
20933static UA_StatusCode
20934UA_CommonVariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
20935 UA_StatusCode retval =
20936 UA_Array_copy(src: src->arrayDimensions, size: src->arrayDimensionsSize,
20937 dst: (void**)&dst->arrayDimensions, type: &UA_TYPES[UA_TYPES_INT32]);
20938 if(retval != UA_STATUSCODE_GOOD)
20939 return retval;
20940 dst->arrayDimensionsSize = src->arrayDimensionsSize;
20941 retval = UA_NodeId_copy(src: &src->dataType, dst: &dst->dataType);
20942 dst->valueRank = src->valueRank;
20943 dst->valueSource = src->valueSource;
20944 if(src->valueSource == UA_VALUESOURCE_DATA) {
20945 retval |= UA_DataValue_copy(src: &src->value.data.value,
20946 dst: &dst->value.data.value);
20947 dst->value.data.callback = src->value.data.callback;
20948 } else
20949 dst->value.dataSource = src->value.dataSource;
20950 return retval;
20951}
20952
20953static UA_StatusCode
20954UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
20955 dst->accessLevel = src->accessLevel;
20956 dst->minimumSamplingInterval = src->minimumSamplingInterval;
20957 dst->historizing = src->historizing;
20958 dst->isDynamic = src->isDynamic;
20959 return UA_CommonVariableNode_copy(src, dst);
20960}
20961
20962static UA_StatusCode
20963UA_VariableTypeNode_copy(const UA_VariableTypeNode *src,
20964 UA_VariableTypeNode *dst) {
20965 dst->isAbstract = src->isAbstract;
20966 return UA_CommonVariableNode_copy(src: (const UA_VariableNode*)src, dst: (UA_VariableNode*)dst);
20967}
20968
20969static UA_StatusCode
20970UA_MethodNode_copy(const UA_MethodNode *src, UA_MethodNode *dst) {
20971 dst->executable = src->executable;
20972 dst->method = src->method;
20973#if UA_MULTITHREADING >= 100
20974 dst->async = src->async;
20975#endif
20976 return UA_STATUSCODE_GOOD;
20977}
20978
20979static UA_StatusCode
20980UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectTypeNode *dst) {
20981 dst->isAbstract = src->isAbstract;
20982 dst->lifecycle = src->lifecycle;
20983 return UA_STATUSCODE_GOOD;
20984}
20985
20986static UA_StatusCode
20987UA_ReferenceTypeNode_copy(const UA_ReferenceTypeNode *src,
20988 UA_ReferenceTypeNode *dst) {
20989 dst->isAbstract = src->isAbstract;
20990 dst->symmetric = src->symmetric;
20991 dst->referenceTypeIndex = src->referenceTypeIndex;
20992 dst->subTypes = src->subTypes;
20993 return UA_LocalizedText_copy(src: &src->inverseName, dst: &dst->inverseName);
20994}
20995
20996static UA_StatusCode
20997UA_DataTypeNode_copy(const UA_DataTypeNode *src, UA_DataTypeNode *dst) {
20998 dst->isAbstract = src->isAbstract;
20999 return UA_STATUSCODE_GOOD;
21000}
21001
21002static UA_StatusCode
21003UA_ViewNode_copy(const UA_ViewNode *src, UA_ViewNode *dst) {
21004 dst->containsNoLoops = src->containsNoLoops;
21005 dst->eventNotifier = src->eventNotifier;
21006 return UA_STATUSCODE_GOOD;
21007}
21008
21009UA_StatusCode
21010UA_Node_copy(const UA_Node *src, UA_Node *dst) {
21011 const UA_NodeHead *srchead = &src->head;
21012 UA_NodeHead *dsthead = &dst->head;
21013 if(srchead->nodeClass != dsthead->nodeClass)
21014 return UA_STATUSCODE_BADINTERNALERROR;
21015
21016 /* Copy standard content */
21017 UA_StatusCode retval = UA_NodeId_copy(src: &srchead->nodeId, dst: &dsthead->nodeId);
21018 retval |= UA_QualifiedName_copy(src: &srchead->browseName, dst: &dsthead->browseName);
21019 retval |= UA_LocalizedText_copy(src: &srchead->displayName, dst: &dsthead->displayName);
21020 retval |= UA_LocalizedText_copy(src: &srchead->description, dst: &dsthead->description);
21021 dsthead->writeMask = srchead->writeMask;
21022 dsthead->context = srchead->context;
21023 dsthead->constructed = srchead->constructed;
21024#ifdef UA_ENABLE_SUBSCRIPTIONS
21025 dsthead->monitoredItems = srchead->monitoredItems;
21026#endif
21027 if(retval != UA_STATUSCODE_GOOD) {
21028 UA_Node_clear(node: dst);
21029 return retval;
21030 }
21031
21032 /* Copy the references */
21033 dsthead->references = NULL;
21034 if(srchead->referencesSize > 0) {
21035 dsthead->references = (UA_NodeReferenceKind*)
21036 UA_calloc(nmemb: srchead->referencesSize, size: sizeof(UA_NodeReferenceKind));
21037 if(!dsthead->references) {
21038 UA_Node_clear(node: dst);
21039 return UA_STATUSCODE_BADOUTOFMEMORY;
21040 }
21041 dsthead->referencesSize = srchead->referencesSize;
21042
21043 for(size_t i = 0; i < srchead->referencesSize; ++i) {
21044 UA_NodeReferenceKind *srefs = &srchead->references[i];
21045 UA_NodeReferenceKind *drefs = &dsthead->references[i];
21046 drefs->referenceTypeIndex = srefs->referenceTypeIndex;
21047 drefs->isInverse = srefs->isInverse;
21048 drefs->hasRefTree = srefs->hasRefTree; /* initially empty */
21049
21050 /* Copy all the targets */
21051 const UA_ReferenceTarget *t = NULL;
21052 while((t = UA_NodeReferenceKind_iterate(rk: srefs, prev: t))) {
21053 retval = addReferenceTarget(refs: drefs, target: t->targetId, targetNameHash: t->targetNameHash);
21054 if(retval != UA_STATUSCODE_GOOD) {
21055 UA_Node_clear(node: dst);
21056 return retval;
21057 }
21058 }
21059 }
21060 }
21061
21062 /* Copy unique content of the nodeclass */
21063 switch(src->head.nodeClass) {
21064 case UA_NODECLASS_OBJECT:
21065 retval = UA_ObjectNode_copy(src: &src->objectNode, dst: &dst->objectNode);
21066 break;
21067 case UA_NODECLASS_VARIABLE:
21068 retval = UA_VariableNode_copy(src: &src->variableNode, dst: &dst->variableNode);
21069 break;
21070 case UA_NODECLASS_METHOD:
21071 retval = UA_MethodNode_copy(src: &src->methodNode, dst: &dst->methodNode);
21072 break;
21073 case UA_NODECLASS_OBJECTTYPE:
21074 retval = UA_ObjectTypeNode_copy(src: &src->objectTypeNode, dst: &dst->objectTypeNode);
21075 break;
21076 case UA_NODECLASS_VARIABLETYPE:
21077 retval = UA_VariableTypeNode_copy(src: &src->variableTypeNode, dst: &dst->variableTypeNode);
21078 break;
21079 case UA_NODECLASS_REFERENCETYPE:
21080 retval = UA_ReferenceTypeNode_copy(src: &src->referenceTypeNode, dst: &dst->referenceTypeNode);
21081 break;
21082 case UA_NODECLASS_DATATYPE:
21083 retval = UA_DataTypeNode_copy(src: &src->dataTypeNode, dst: &dst->dataTypeNode);
21084 break;
21085 case UA_NODECLASS_VIEW:
21086 retval = UA_ViewNode_copy(src: &src->viewNode, dst: &dst->viewNode);
21087 break;
21088 default:
21089 break;
21090 }
21091
21092 if(retval != UA_STATUSCODE_GOOD)
21093 UA_Node_clear(node: dst);
21094
21095 return retval;
21096}
21097
21098UA_Node *
21099UA_Node_copy_alloc(const UA_Node *src) {
21100 size_t nodesize = 0;
21101 switch(src->head.nodeClass) {
21102 case UA_NODECLASS_OBJECT:
21103 nodesize = sizeof(UA_ObjectNode);
21104 break;
21105 case UA_NODECLASS_VARIABLE:
21106 nodesize = sizeof(UA_VariableNode);
21107 break;
21108 case UA_NODECLASS_METHOD:
21109 nodesize = sizeof(UA_MethodNode);
21110 break;
21111 case UA_NODECLASS_OBJECTTYPE:
21112 nodesize = sizeof(UA_ObjectTypeNode);
21113 break;
21114 case UA_NODECLASS_VARIABLETYPE:
21115 nodesize = sizeof(UA_VariableTypeNode);
21116 break;
21117 case UA_NODECLASS_REFERENCETYPE:
21118 nodesize = sizeof(UA_ReferenceTypeNode);
21119 break;
21120 case UA_NODECLASS_DATATYPE:
21121 nodesize = sizeof(UA_DataTypeNode);
21122 break;
21123 case UA_NODECLASS_VIEW:
21124 nodesize = sizeof(UA_ViewNode);
21125 break;
21126 default:
21127 return NULL;
21128 }
21129
21130 UA_Node *dst = (UA_Node*)UA_calloc(nmemb: 1, size: nodesize);
21131 if(!dst)
21132 return NULL;
21133
21134 dst->head.nodeClass = src->head.nodeClass;
21135
21136 UA_StatusCode retval = UA_Node_copy(src, dst);
21137 if(retval != UA_STATUSCODE_GOOD) {
21138 UA_free(ptr: dst);
21139 return NULL;
21140 }
21141 return dst;
21142}
21143/******************************/
21144/* Copy Attributes into Nodes */
21145/******************************/
21146
21147static UA_StatusCode
21148copyStandardAttributes(UA_NodeHead *head, const UA_NodeAttributes *attr) {
21149 /* UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId); */
21150 /* UA_QualifiedName_copy(&item->browseName, &node->browseName); */
21151
21152 head->writeMask = attr->writeMask;
21153 UA_StatusCode retval = UA_LocalizedText_copy(src: &attr->description, dst: &head->description);
21154 /* The new nodeset format has optional display names:
21155 * https://github.com/open62541/open62541/issues/2627. If the display name
21156 * is NULL, take the name part of the browse name */
21157 if(attr->displayName.text.length == 0)
21158 retval |= UA_String_copy(src: &head->browseName.name, dst: &head->displayName.text);
21159 else
21160 retval |= UA_LocalizedText_copy(src: &attr->displayName, dst: &head->displayName);
21161 return retval;
21162}
21163
21164static UA_StatusCode
21165copyCommonVariableAttributes(UA_VariableNode *node,
21166 const UA_VariableAttributes *attr) {
21167 /* Copy the array dimensions */
21168 UA_StatusCode retval =
21169 UA_Array_copy(src: attr->arrayDimensions, size: attr->arrayDimensionsSize,
21170 dst: (void**)&node->arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]);
21171 if(retval != UA_STATUSCODE_GOOD)
21172 return retval;
21173 node->arrayDimensionsSize = attr->arrayDimensionsSize;
21174
21175 /* Data type and value rank */
21176 retval = UA_NodeId_copy(src: &attr->dataType, dst: &node->dataType);
21177 if(retval != UA_STATUSCODE_GOOD)
21178 return retval;
21179 node->valueRank = attr->valueRank;
21180
21181 /* Copy the value */
21182 retval = UA_Variant_copy(src: &attr->value, dst: &node->value.data.value.value);
21183 node->valueSource = UA_VALUESOURCE_DATA;
21184 node->value.data.value.hasValue = (node->value.data.value.value.type != NULL);
21185
21186 return retval;
21187}
21188
21189static UA_StatusCode
21190copyVariableNodeAttributes(UA_VariableNode *vnode,
21191 const UA_VariableAttributes *attr) {
21192 vnode->accessLevel = attr->accessLevel;
21193 vnode->historizing = attr->historizing;
21194 vnode->minimumSamplingInterval = attr->minimumSamplingInterval;
21195 return copyCommonVariableAttributes(node: vnode, attr);
21196}
21197
21198static UA_StatusCode
21199copyVariableTypeNodeAttributes(UA_VariableTypeNode *vtnode,
21200 const UA_VariableTypeAttributes *attr) {
21201 vtnode->isAbstract = attr->isAbstract;
21202 return copyCommonVariableAttributes(node: (UA_VariableNode*)vtnode,
21203 attr: (const UA_VariableAttributes*)attr);
21204}
21205
21206static UA_StatusCode
21207copyObjectNodeAttributes(UA_ObjectNode *onode, const UA_ObjectAttributes *attr) {
21208 onode->eventNotifier = attr->eventNotifier;
21209 return UA_STATUSCODE_GOOD;
21210}
21211
21212static UA_StatusCode
21213copyReferenceTypeNodeAttributes(UA_ReferenceTypeNode *rtnode,
21214 const UA_ReferenceTypeAttributes *attr) {
21215 rtnode->isAbstract = attr->isAbstract;
21216 rtnode->symmetric = attr->symmetric;
21217 return UA_LocalizedText_copy(src: &attr->inverseName, dst: &rtnode->inverseName);
21218}
21219
21220static UA_StatusCode
21221copyObjectTypeNodeAttributes(UA_ObjectTypeNode *otnode,
21222 const UA_ObjectTypeAttributes *attr) {
21223 otnode->isAbstract = attr->isAbstract;
21224 return UA_STATUSCODE_GOOD;
21225}
21226
21227static UA_StatusCode
21228copyViewNodeAttributes(UA_ViewNode *vnode, const UA_ViewAttributes *attr) {
21229 vnode->containsNoLoops = attr->containsNoLoops;
21230 vnode->eventNotifier = attr->eventNotifier;
21231 return UA_STATUSCODE_GOOD;
21232}
21233
21234static UA_StatusCode
21235copyDataTypeNodeAttributes(UA_DataTypeNode *dtnode,
21236 const UA_DataTypeAttributes *attr) {
21237 dtnode->isAbstract = attr->isAbstract;
21238 return UA_STATUSCODE_GOOD;
21239}
21240
21241static UA_StatusCode
21242copyMethodNodeAttributes(UA_MethodNode *mnode,
21243 const UA_MethodAttributes *attr) {
21244 mnode->executable = attr->executable;
21245 return UA_STATUSCODE_GOOD;
21246}
21247
21248#define CHECK_ATTRIBUTES(TYPE) \
21249 if(attributeType != &UA_TYPES[UA_TYPES_##TYPE]) { \
21250 retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID; \
21251 break; \
21252 }
21253
21254UA_StatusCode
21255UA_Node_setAttributes(UA_Node *node, const void *attributes, const UA_DataType *attributeType) {
21256 /* Copy the attributes into the node */
21257 UA_StatusCode retval = UA_STATUSCODE_GOOD;
21258 switch(node->head.nodeClass) {
21259 case UA_NODECLASS_OBJECT:
21260 CHECK_ATTRIBUTES(OBJECTATTRIBUTES);
21261 retval = copyObjectNodeAttributes(onode: &node->objectNode,
21262 attr: (const UA_ObjectAttributes*)attributes);
21263 break;
21264 case UA_NODECLASS_VARIABLE:
21265 CHECK_ATTRIBUTES(VARIABLEATTRIBUTES);
21266 retval = copyVariableNodeAttributes(vnode: &node->variableNode,
21267 attr: (const UA_VariableAttributes*)attributes);
21268 break;
21269 case UA_NODECLASS_OBJECTTYPE:
21270 CHECK_ATTRIBUTES(OBJECTTYPEATTRIBUTES);
21271 retval = copyObjectTypeNodeAttributes(otnode: &node->objectTypeNode,
21272 attr: (const UA_ObjectTypeAttributes*)attributes);
21273 break;
21274 case UA_NODECLASS_VARIABLETYPE:
21275 CHECK_ATTRIBUTES(VARIABLETYPEATTRIBUTES);
21276 retval = copyVariableTypeNodeAttributes(vtnode: &node->variableTypeNode,
21277 attr: (const UA_VariableTypeAttributes*)attributes);
21278 break;
21279 case UA_NODECLASS_REFERENCETYPE:
21280 CHECK_ATTRIBUTES(REFERENCETYPEATTRIBUTES);
21281 retval = copyReferenceTypeNodeAttributes(rtnode: &node->referenceTypeNode,
21282 attr: (const UA_ReferenceTypeAttributes*)attributes);
21283 break;
21284 case UA_NODECLASS_DATATYPE:
21285 CHECK_ATTRIBUTES(DATATYPEATTRIBUTES);
21286 retval = copyDataTypeNodeAttributes(dtnode: &node->dataTypeNode,
21287 attr: (const UA_DataTypeAttributes*)attributes);
21288 break;
21289 case UA_NODECLASS_VIEW:
21290 CHECK_ATTRIBUTES(VIEWATTRIBUTES);
21291 retval = copyViewNodeAttributes(vnode: &node->viewNode, attr: (const UA_ViewAttributes*)attributes);
21292 break;
21293 case UA_NODECLASS_METHOD:
21294 CHECK_ATTRIBUTES(METHODATTRIBUTES);
21295 retval = copyMethodNodeAttributes(mnode: &node->methodNode, attr: (const UA_MethodAttributes*)attributes);
21296 break;
21297 case UA_NODECLASS_UNSPECIFIED:
21298 default:
21299 retval = UA_STATUSCODE_BADNODECLASSINVALID;
21300 }
21301
21302 if(retval == UA_STATUSCODE_GOOD)
21303 retval = copyStandardAttributes(head: &node->head, attr: (const UA_NodeAttributes*)attributes);
21304 if(retval != UA_STATUSCODE_GOOD)
21305 UA_Node_clear(node);
21306 return retval;
21307}
21308
21309/*********************/
21310/* Manage References */
21311/*********************/
21312
21313static UA_StatusCode
21314addReferenceTarget(UA_NodeReferenceKind *rk, UA_NodePointer targetId,
21315 UA_UInt32 targetNameHash) {
21316 /* Insert into array */
21317 if(!rk->hasRefTree) {
21318 UA_ReferenceTarget *newRefs = (UA_ReferenceTarget*)
21319 UA_realloc(ptr: rk->targets.array,
21320 size: sizeof(UA_ReferenceTarget) * (rk->targetsSize + 1));
21321 if(!newRefs)
21322 return UA_STATUSCODE_BADOUTOFMEMORY;
21323 rk->targets.array = newRefs;
21324
21325 UA_StatusCode retval =
21326 UA_NodePointer_copy(in: targetId,
21327 out: &rk->targets.array[rk->targetsSize].targetId);
21328 rk->targets.array[rk->targetsSize].targetNameHash = targetNameHash;
21329 if(retval != UA_STATUSCODE_GOOD) {
21330 if(rk->targetsSize == 0) {
21331 UA_free(ptr: rk->targets.array);
21332 rk->targets.array = NULL;
21333 }
21334 return retval;
21335 }
21336 rk->targetsSize++;
21337 return UA_STATUSCODE_GOOD;
21338 }
21339
21340 /* Insert into tree */
21341 UA_ReferenceTargetTreeElem *entry = (UA_ReferenceTargetTreeElem*)
21342 UA_malloc(size: sizeof(UA_ReferenceTargetTreeElem));
21343 if(!entry)
21344 return UA_STATUSCODE_BADOUTOFMEMORY;
21345
21346 UA_StatusCode retval =
21347 UA_NodePointer_copy(in: targetId, out: &entry->target.targetId);
21348 if(retval != UA_STATUSCODE_GOOD) {
21349 UA_free(ptr: entry);
21350 return retval;
21351 }
21352
21353 /* <-- The point of no return --> */
21354
21355 UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: targetId);
21356 entry->targetIdHash = UA_ExpandedNodeId_hash(n: &en);
21357 entry->target.targetNameHash = targetNameHash;
21358
21359 /* Insert to the id lookup binary search tree. Only the root is kept in refs
21360 * to save space. */
21361 struct aa_head _refIdTree = refIdTree;
21362 _refIdTree.root = rk->targets.tree.idTreeRoot;
21363 aa_insert(head: &_refIdTree, elem: entry);
21364 rk->targets.tree.idTreeRoot = _refIdTree.root;
21365
21366 /* Insert to the name lookup binary search tree */
21367 struct aa_head _refNameTree = refNameTree;
21368 _refNameTree.root = rk->targets.tree.nameTreeRoot;
21369 aa_insert(head: &_refNameTree, elem: entry);
21370 rk->targets.tree.nameTreeRoot = _refNameTree.root;
21371
21372 rk->targetsSize++;
21373
21374 return UA_STATUSCODE_GOOD;
21375}
21376
21377static UA_StatusCode
21378addReferenceKind(UA_NodeHead *head, UA_Byte refTypeIndex, UA_Boolean isForward,
21379 const UA_NodePointer target, UA_UInt32 targetBrowseNameHash) {
21380 UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*)
21381 UA_realloc(ptr: head->references,
21382 size: sizeof(UA_NodeReferenceKind) * (head->referencesSize+1));
21383 if(!refs)
21384 return UA_STATUSCODE_BADOUTOFMEMORY;
21385 head->references = refs;
21386
21387 UA_NodeReferenceKind *newRef = &refs[head->referencesSize];
21388 memset(s: newRef, c: 0, n: sizeof(UA_NodeReferenceKind));
21389 newRef->referenceTypeIndex = refTypeIndex;
21390 newRef->isInverse = !isForward;
21391 UA_StatusCode retval =
21392 addReferenceTarget(rk: newRef, targetId: target, targetNameHash: targetBrowseNameHash);
21393 if(retval != UA_STATUSCODE_GOOD) {
21394 if(head->referencesSize == 0) {
21395 UA_free(ptr: head->references);
21396 head->references = NULL;
21397 }
21398 return retval;
21399 }
21400
21401 head->referencesSize++;
21402 return UA_STATUSCODE_GOOD;
21403}
21404
21405UA_StatusCode
21406UA_Node_addReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward,
21407 const UA_ExpandedNodeId *targetNodeId,
21408 UA_UInt32 targetBrowseNameHash) {
21409 /* Find the matching reference kind */
21410 for(size_t i = 0; i < node->head.referencesSize; ++i) {
21411 UA_NodeReferenceKind *refs = &node->head.references[i];
21412
21413 /* Reference direction does not match */
21414 if(refs->isInverse == isForward)
21415 continue;
21416
21417 /* Reference type does not match */
21418 if(refs->referenceTypeIndex != refTypeIndex)
21419 continue;
21420
21421 /* Does an identical reference already exist? */
21422 const UA_ReferenceTarget *found =
21423 UA_NodeReferenceKind_findTarget(rk: refs, targetId: targetNodeId);
21424 if(found)
21425 return UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
21426
21427 /* Add to existing ReferenceKind */
21428 return addReferenceTarget(rk: refs, targetId: UA_NodePointer_fromExpandedNodeId(id: targetNodeId),
21429 targetNameHash: targetBrowseNameHash);
21430 }
21431
21432 /* Add new ReferenceKind for the target */
21433 return addReferenceKind(head: &node->head, refTypeIndex, isForward,
21434 target: UA_NodePointer_fromExpandedNodeId(id: targetNodeId),
21435 targetBrowseNameHash);
21436
21437}
21438
21439UA_StatusCode
21440UA_Node_deleteReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward,
21441 const UA_ExpandedNodeId *targetNodeId) {
21442 struct aa_head _refIdTree = refIdTree;
21443 struct aa_head _refNameTree = refNameTree;
21444
21445 UA_NodeHead *head = &node->head;
21446 for(size_t i = 0; i < head->referencesSize; i++) {
21447 UA_NodeReferenceKind *refs = &head->references[i];
21448 if(isForward == refs->isInverse)
21449 continue;
21450 if(refTypeIndex != refs->referenceTypeIndex)
21451 continue;
21452
21453 /* Cast out the const qualifier (hack!) */
21454 UA_ReferenceTarget *target = (UA_ReferenceTarget*)(uintptr_t)
21455 UA_NodeReferenceKind_findTarget(rk: refs, targetId: targetNodeId);
21456 if(!target)
21457 continue;
21458
21459 /* Ok, delete the reference. Cannot fail */
21460 refs->targetsSize--;
21461
21462 if(!refs->hasRefTree) {
21463 /* Remove from array */
21464 UA_NodePointer_clear(np: &target->targetId);
21465
21466 /* Elements remaining. Realloc. */
21467 if(refs->targetsSize > 0) {
21468 if(target != &refs->targets.array[refs->targetsSize])
21469 *target = refs->targets.array[refs->targetsSize];
21470 UA_ReferenceTarget *newRefs = (UA_ReferenceTarget*)
21471 UA_realloc(ptr: refs->targets.array,
21472 size: sizeof(UA_ReferenceTarget) * refs->targetsSize);
21473 if(newRefs)
21474 refs->targets.array = newRefs;
21475 return UA_STATUSCODE_GOOD; /* Realloc allowed to fail */
21476 }
21477
21478 /* Remove the last target. Remove the ReferenceKind below */
21479 UA_free(ptr: refs->targets.array);
21480 } else {
21481 /* Remove from the tree */
21482 _refIdTree.root = refs->targets.tree.idTreeRoot;
21483 aa_remove(head: &_refIdTree, elem: target);
21484 refs->targets.tree.idTreeRoot = _refIdTree.root;
21485
21486 _refNameTree.root = refs->targets.tree.nameTreeRoot;
21487 aa_remove(head: &_refNameTree, elem: target);
21488 refs->targets.tree.nameTreeRoot = _refNameTree.root;
21489
21490 UA_NodePointer_clear(np: &target->targetId);
21491 UA_free(ptr: target);
21492 if(refs->targets.tree.idTreeRoot)
21493 return UA_STATUSCODE_GOOD; /* At least one target remains */
21494 }
21495
21496 /* No targets remaining. Remove the ReferenceKind. */
21497 head->referencesSize--;
21498 if(head->referencesSize > 0) {
21499 /* No target for the ReferenceType remaining. Remove and shrink down
21500 * allocated buffer. Ignore errors in case memory buffer could not
21501 * be shrinked down. */
21502 if(i != head->referencesSize)
21503 head->references[i] = head->references[node->head.referencesSize];
21504 UA_NodeReferenceKind *newRefs = (UA_NodeReferenceKind*)
21505 UA_realloc(ptr: head->references,
21506 size: sizeof(UA_NodeReferenceKind) * head->referencesSize);
21507 if(newRefs)
21508 head->references = newRefs;
21509 } else {
21510 /* No remaining references of any ReferenceType */
21511 UA_free(ptr: head->references);
21512 head->references = NULL;
21513 }
21514 return UA_STATUSCODE_GOOD;
21515 }
21516 return UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED;
21517}
21518
21519void
21520UA_Node_deleteReferencesSubset(UA_Node *node, const UA_ReferenceTypeSet *keepSet) {
21521 UA_NodeHead *head = &node->head;
21522 struct aa_head _refIdTree = refIdTree;
21523 for(size_t i = 0; i < head->referencesSize; i++) {
21524 /* Keep the references of this type? */
21525 UA_NodeReferenceKind *refs = &head->references[i];
21526 if(UA_ReferenceTypeSet_contains(set: keepSet, index: refs->referenceTypeIndex))
21527 continue;
21528
21529 /* Remove all target entries. Don't remove entries from browseName tree.
21530 * The entire ReferenceKind will be removed anyway. */
21531 if(!refs->hasRefTree) {
21532 for(size_t j = 0; j < refs->targetsSize; j++)
21533 UA_NodePointer_clear(np: &refs->targets.array[j].targetId);
21534 UA_free(ptr: refs->targets.array);
21535 } else {
21536 _refIdTree.root = refs->targets.tree.idTreeRoot;
21537 while(_refIdTree.root) {
21538 UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
21539 ((uintptr_t)_refIdTree.root -
21540 offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
21541 aa_remove(head: &_refIdTree, elem);
21542 UA_NodePointer_clear(np: &elem->target.targetId);
21543 UA_free(ptr: elem);
21544 }
21545 }
21546
21547 /* Move last references-kind entry to this position. Don't memcpy over
21548 * the same position. Decrease i to repeat at this location. */
21549 head->referencesSize--;
21550 if(i != head->referencesSize) {
21551 head->references[i] = head->references[head->referencesSize];
21552 i--;
21553 }
21554 }
21555
21556 if(head->referencesSize > 0) {
21557 /* Realloc to save memory. Ignore if realloc fails. */
21558 UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*)
21559 UA_realloc(ptr: head->references,
21560 size: sizeof(UA_NodeReferenceKind) * head->referencesSize);
21561 if(refs)
21562 head->references = refs;
21563 } else {
21564 /* The array is empty. Remove. */
21565 UA_free(ptr: head->references);
21566 head->references = NULL;
21567 }
21568}
21569
21570void UA_Node_deleteReferences(UA_Node *node) {
21571 UA_ReferenceTypeSet noRefs;
21572 UA_ReferenceTypeSet_init(set: &noRefs);
21573 UA_Node_deleteReferencesSubset(node, keepSet: &noRefs);
21574}
21575
21576/**** amalgamated original file "/src/server/ua_server.c" ****/
21577
21578/* This Source Code Form is subject to the terms of the Mozilla Public
21579 * License, v. 2.0. If a copy of the MPL was not distributed with this
21580 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
21581 *
21582 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
21583 * Copyright 2014-2017 (c) Florian Palm
21584 * Copyright 2015-2016 (c) Sten Grüner
21585 * Copyright 2015-2016 (c) Chris Iatrou
21586 * Copyright 2015 (c) LEvertz
21587 * Copyright 2015-2016 (c) Oleksiy Vasylyev
21588 * Copyright 2016 (c) Julian Grothoff
21589 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
21590 * Copyright 2016 (c) Lorenz Haas
21591 * Copyright 2017 (c) frax2222
21592 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
21593 * Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
21594 * Copyright 2019 (c) Kalycito Infotech Private Limited
21595 * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes)
21596 * Copyright 2022 (c) Fraunhofer IOSB (Author: Andreas Ebner)
21597 */
21598
21599
21600#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
21601#endif
21602
21603
21604#ifdef UA_ENABLE_SUBSCRIPTIONS
21605#endif
21606
21607#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
21608#include <valgrind/memcheck.h>
21609#endif
21610
21611#define STARTCHANNELID 1
21612#define STARTTOKENID 1
21613
21614/**********************/
21615/* Namespace Handling */
21616/**********************/
21617
21618/* The NS1 Uri can be changed by the user to some custom string. This method is
21619 * called to initialize the NS1 Uri if it is not set before to the default
21620 * Application URI.
21621 *
21622 * This is done as soon as the Namespace Array is read or written via node value
21623 * read / write services, or UA_Server_addNamespace, or UA_Server_getNamespaceByIndex
21624 * UA_Server_getNamespaceByName or UA_Server_run_startup is called.
21625 *
21626 * Therefore one has to set the custom NS1 URI before one of the previously
21627 * mentioned steps. */
21628void
21629setupNs1Uri(UA_Server *server) {
21630 if(!server->namespaces[1].data) {
21631 UA_String_copy(src: &server->config.applicationDescription.applicationUri,
21632 dst: &server->namespaces[1]);
21633 }
21634}
21635
21636UA_UInt16 addNamespace(UA_Server *server, const UA_String name) {
21637 /* ensure that the uri for ns1 is set up from the app description */
21638 setupNs1Uri(server);
21639
21640 /* Check if the namespace already exists in the server's namespace array */
21641 for(UA_UInt16 i = 0; i < server->namespacesSize; ++i) {
21642 if(UA_String_equal(s1: &name, s2: &server->namespaces[i]))
21643 return i;
21644 }
21645
21646 /* Make the array bigger */
21647 UA_String *newNS = (UA_String*)UA_realloc(ptr: server->namespaces,
21648 size: sizeof(UA_String) * (server->namespacesSize + 1));
21649 UA_CHECK_MEM(newNS, return 0);
21650
21651 server->namespaces = newNS;
21652
21653 /* Copy the namespace string */
21654 UA_StatusCode retval = UA_String_copy(src: &name, dst: &server->namespaces[server->namespacesSize]);
21655 UA_CHECK_STATUS(retval, return 0);
21656
21657 /* Announce the change (otherwise, the array appears unchanged) */
21658 ++server->namespacesSize;
21659 return (UA_UInt16)(server->namespacesSize - 1);
21660}
21661
21662UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
21663 /* Override const attribute to get string (dirty hack) */
21664 UA_String nameString;
21665 nameString.length = strlen(s: name);
21666 nameString.data = (UA_Byte*)(uintptr_t)name;
21667 UA_LOCK(&server->serviceMutex);
21668 UA_UInt16 retVal = addNamespace(server, name: nameString);
21669 UA_UNLOCK(&server->serviceMutex);
21670 return retVal;
21671}
21672
21673UA_ServerConfig*
21674UA_Server_getConfig(UA_Server *server) {
21675 UA_CHECK_MEM(server, return NULL);
21676 return &server->config;
21677}
21678
21679UA_StatusCode
21680getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
21681 size_t *foundIndex) {
21682 /* ensure that the uri for ns1 is set up from the app description */
21683 setupNs1Uri(server);
21684 UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND;
21685 for(size_t idx = 0; idx < server->namespacesSize; idx++) {
21686 if(UA_String_equal(s1: &server->namespaces[idx], s2: &namespaceUri)) {
21687 (*foundIndex) = idx;
21688 res = UA_STATUSCODE_GOOD;
21689 break;
21690 }
21691 }
21692 return res;
21693}
21694
21695UA_StatusCode
21696getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
21697 UA_String *foundUri) {
21698 /* ensure that the uri for ns1 is set up from the app description */
21699 setupNs1Uri(server);
21700 UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND;
21701 if(namespaceIndex >= server->namespacesSize)
21702 return res;
21703 res = UA_String_copy(src: &server->namespaces[namespaceIndex], dst: foundUri);
21704 return res;
21705}
21706
21707UA_StatusCode
21708UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
21709 size_t *foundIndex) {
21710 UA_LOCK(&server->serviceMutex);
21711 UA_StatusCode res = getNamespaceByName(server, namespaceUri, foundIndex);
21712 UA_UNLOCK(&server->serviceMutex);
21713 return res;
21714}
21715
21716UA_StatusCode
21717UA_Server_getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
21718 UA_String *foundUri) {
21719 UA_LOCK(&server->serviceMutex);
21720 UA_StatusCode res = getNamespaceByIndex(server, namespaceIndex, foundUri);
21721 UA_UNLOCK(&server->serviceMutex);
21722 return res;
21723}
21724
21725UA_StatusCode
21726UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
21727 UA_NodeIteratorCallback callback, void *handle) {
21728 UA_BrowseDescription bd;
21729 UA_BrowseDescription_init(p: &bd);
21730 bd.nodeId = parentNodeId;
21731 bd.browseDirection = UA_BROWSEDIRECTION_BOTH;
21732 bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_ISFORWARD;
21733
21734 UA_BrowseResult br = UA_Server_browse(server, maxReferences: 0, bd: &bd);
21735 UA_StatusCode res = br.statusCode;
21736 UA_CHECK_STATUS(res, goto cleanup);
21737
21738 for(size_t i = 0; i < br.referencesSize; i++) {
21739 if(!UA_ExpandedNodeId_isLocal(n: &br.references[i].nodeId))
21740 continue;
21741 res = callback(br.references[i].nodeId.nodeId, !br.references[i].isForward,
21742 br.references[i].referenceTypeId, handle);
21743 UA_CHECK_STATUS(res, goto cleanup);
21744 }
21745cleanup:
21746 UA_BrowseResult_clear(p: &br);
21747 return res;
21748}
21749
21750/********************/
21751/* Server Lifecycle */
21752/********************/
21753
21754static void
21755serverExecuteRepeatedCallback(UA_Server *server, UA_ApplicationCallback cb,
21756 void *callbackApplication, void *data);
21757
21758/* The server needs to be stopped before it can be deleted */
21759void UA_Server_delete(UA_Server *server) {
21760 UA_LOCK(&server->serviceMutex);
21761
21762 UA_Server_deleteSecureChannels(server);
21763 session_list_entry *current, *temp;
21764 LIST_FOREACH_SAFE(current, &server->sessions, pointers, temp) {
21765 UA_Server_removeSession(server, sentry: current, event: UA_DIAGNOSTICEVENT_CLOSE);
21766 }
21767 UA_Array_delete(p: server->namespaces, size: server->namespacesSize, type: &UA_TYPES[UA_TYPES_STRING]);
21768
21769#ifdef UA_ENABLE_SUBSCRIPTIONS
21770 UA_MonitoredItem *mon, *mon_tmp;
21771 LIST_FOREACH_SAFE(mon, &server->localMonitoredItems, listEntry, mon_tmp) {
21772 LIST_REMOVE(mon, listEntry);
21773 UA_MonitoredItem_delete(server, monitoredItem: mon);
21774 }
21775
21776 /* Remove subscriptions without a session */
21777 UA_Subscription *sub, *sub_tmp;
21778 LIST_FOREACH_SAFE(sub, &server->subscriptions, serverListEntry, sub_tmp) {
21779 UA_Subscription_delete(server, sub);
21780 }
21781 UA_assert(server->monitoredItemsSize == 0);
21782 UA_assert(server->subscriptionsSize == 0);
21783
21784#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
21785 UA_ConditionList_delete(server);
21786#endif
21787
21788#endif
21789
21790#ifdef UA_ENABLE_PUBSUB
21791 UA_PubSubManager_delete(server, &server->pubSubManager);
21792#endif
21793
21794#ifdef UA_ENABLE_DISCOVERY
21795 UA_DiscoveryManager_clear(&server->discoveryManager, server);
21796#endif
21797
21798#if UA_MULTITHREADING >= 100
21799 UA_AsyncManager_clear(&server->asyncManager, server);
21800#endif
21801
21802 /* Clean up the Admin Session */
21803 UA_Session_clear(session: &server->adminSession, server);
21804
21805 UA_UNLOCK(&server->serviceMutex); /* The timer has its own mutex */
21806
21807 /* Execute all remaining delayed events and clean up the timer */
21808 UA_Timer_process(t: &server->timer, nowMonotonic: UA_DateTime_nowMonotonic() + 1,
21809 executionCallback: (UA_TimerExecutionCallback)serverExecuteRepeatedCallback, executionApplication: server);
21810 UA_Timer_clear(t: &server->timer);
21811
21812 /* Clean up the config */
21813 UA_ServerConfig_clean(config: &server->config);
21814
21815#if UA_MULTITHREADING >= 100
21816 UA_LOCK_DESTROY(&server->networkMutex);
21817 UA_LOCK_DESTROY(&server->serviceMutex);
21818#endif
21819
21820 /* Delete the server itself */
21821 UA_free(ptr: server);
21822}
21823
21824/* Recurring cleanup. Removing unused and timed-out channels and sessions */
21825static void
21826UA_Server_cleanup(UA_Server *server, void *_) {
21827 UA_LOCK(&server->serviceMutex);
21828 UA_DateTime nowMonotonic = UA_DateTime_nowMonotonic();
21829 UA_Server_cleanupSessions(server, nowMonotonic);
21830 UA_Server_cleanupTimedOutSecureChannels(server, nowMonotonic);
21831#ifdef UA_ENABLE_DISCOVERY
21832 UA_Discovery_cleanupTimedOut(server, nowMonotonic);
21833#endif
21834 UA_UNLOCK(&server->serviceMutex);
21835}
21836
21837/********************/
21838/* Server Lifecycle */
21839/********************/
21840
21841static
21842UA_INLINE
21843UA_Boolean UA_Server_NodestoreIsConfigured(UA_Server *server) {
21844 return server->config.nodestore.getNode != NULL;
21845}
21846
21847static UA_Server *
21848UA_Server_init(UA_Server *server) {
21849
21850 UA_StatusCode res = UA_STATUSCODE_GOOD;
21851 UA_CHECK_FATAL(UA_Server_NodestoreIsConfigured(server), goto cleanup,
21852 &server->config.logger, UA_LOGCATEGORY_SERVER,
21853 "No Nodestore configured in the server"
21854 );
21855
21856 /* Init start time to zero, the actual start time will be sampled in
21857 * UA_Server_run_startup() */
21858 server->startTime = 0;
21859
21860 /* Set a seed for non-cyptographic randomness */
21861#ifndef UA_ENABLE_DETERMINISTIC_RNG
21862 UA_random_seed(seed: (UA_UInt64)UA_DateTime_now());
21863#endif
21864
21865#if UA_MULTITHREADING >= 100
21866 UA_LOCK_INIT(&server->networkMutex);
21867 UA_LOCK_INIT(&server->serviceMutex);
21868#endif
21869
21870 /* Initialize the handling of repeated callbacks */
21871 UA_Timer_init(t: &server->timer);
21872
21873 /* Initialize the adminSession */
21874 UA_Session_init(session: &server->adminSession);
21875 server->adminSession.sessionId.identifierType = UA_NODEIDTYPE_GUID;
21876 server->adminSession.sessionId.identifier.guid.data1 = 1;
21877 server->adminSession.validTill = UA_INT64_MAX;
21878 server->adminSession.sessionName = UA_STRING_ALLOC("Administrator");
21879
21880 /* Create Namespaces 0 and 1
21881 * Ns1 will be filled later with the uri from the app description */
21882 server->namespaces = (UA_String *)UA_Array_new(size: 2, type: &UA_TYPES[UA_TYPES_STRING]);
21883 UA_CHECK_MEM(server->namespaces, goto cleanup);
21884
21885 server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
21886 server->namespaces[1] = UA_STRING_NULL;
21887 server->namespacesSize = 2;
21888
21889 /* Initialize SecureChannel */
21890 TAILQ_INIT(&server->channels);
21891 /* TODO: use an ID that is likely to be unique after a restart */
21892 server->lastChannelId = STARTCHANNELID;
21893 server->lastTokenId = STARTTOKENID;
21894
21895 /* Initialize Session Management */
21896 LIST_INIT(&server->sessions);
21897 server->sessionCount = 0;
21898
21899#if UA_MULTITHREADING >= 100
21900 UA_AsyncManager_init(&server->asyncManager, server);
21901#endif
21902
21903 /* Initialized discovery */
21904#ifdef UA_ENABLE_DISCOVERY
21905 UA_DiscoveryManager_init(&server->discoveryManager, server);
21906#endif
21907
21908 /* Add a regular callback for cleanup and maintenance. With a 10s interval. */
21909 UA_Server_addRepeatedCallback(server, callback: (UA_ServerCallback)UA_Server_cleanup, NULL,
21910 interval_ms: 10000.0, NULL);
21911
21912 /* Initialize namespace 0*/
21913 res = UA_Server_initNS0(server);
21914 UA_CHECK_STATUS(res, goto cleanup);
21915
21916#ifdef UA_ENABLE_PUBSUB
21917 /* Build PubSub information model */
21918#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
21919 UA_Server_initPubSubNS0(server);
21920#endif
21921
21922#ifdef UA_ENABLE_PUBSUB_MONITORING
21923 /* setup default PubSub monitoring callbacks */
21924 res = UA_PubSubManager_setDefaultMonitoringCallbacks(&server->config.pubSubConfig.monitoringInterface);
21925 UA_CHECK_STATUS(res, goto cleanup);
21926#endif /* UA_ENABLE_PUBSUB_MONITORING */
21927#endif /* UA_ENABLE_PUBSUB */
21928 return server;
21929
21930 cleanup:
21931 UA_Server_delete(server);
21932 return NULL;
21933}
21934
21935UA_Server *
21936UA_Server_newWithConfig(UA_ServerConfig *config) {
21937 UA_CHECK_MEM(config, return NULL);
21938
21939 UA_Server *server = (UA_Server *)UA_calloc(nmemb: 1, size: sizeof(UA_Server));
21940 UA_CHECK_MEM(server, UA_ServerConfig_clean(config); return NULL);
21941
21942 server->config = *config;
21943 /* The config might have been "moved" into the server struct. Ensure that
21944 * the logger pointer is correct. */
21945 for(size_t i = 0; i < server->config.securityPoliciesSize; i++)
21946 server->config.securityPolicies[i].logger = &server->config.logger;
21947
21948 /* Reset the old config */
21949 memset(s: config, c: 0, n: sizeof(UA_ServerConfig));
21950 return UA_Server_init(server);
21951}
21952
21953/* Returns if the server should be shut down immediately */
21954static UA_Boolean
21955setServerShutdown(UA_Server *server) {
21956 if(server->endTime != 0)
21957 return false;
21958 if(server->config.shutdownDelay == 0)
21959 return true;
21960 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
21961 msg: "Shutting down the server with a delay of %i ms", (int)server->config.shutdownDelay);
21962 server->endTime = UA_DateTime_now() + (UA_DateTime)(server->config.shutdownDelay * UA_DATETIME_MSEC);
21963 return false;
21964}
21965
21966/*******************/
21967/* Timed Callbacks */
21968/*******************/
21969
21970UA_StatusCode
21971UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback,
21972 void *data, UA_DateTime date, UA_UInt64 *callbackId) {
21973 UA_LOCK(&server->serviceMutex);
21974 UA_StatusCode retval =
21975 UA_Timer_addTimedCallback(t: &server->timer,
21976 callback: (UA_ApplicationCallback)callback,
21977 application: server, data, date, callbackId);
21978 UA_UNLOCK(&server->serviceMutex);
21979 return retval;
21980}
21981
21982UA_StatusCode
21983addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
21984 void *data, UA_Double interval_ms,
21985 UA_UInt64 *callbackId) {
21986 return UA_Timer_addRepeatedCallback(t: &server->timer,
21987 callback: (UA_ApplicationCallback)callback,
21988 application: server, data, interval_ms, NULL,
21989 timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, callbackId);
21990}
21991
21992UA_StatusCode
21993UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
21994 void *data, UA_Double interval_ms,
21995 UA_UInt64 *callbackId) {
21996 UA_LOCK(&server->serviceMutex);
21997 UA_StatusCode retval =
21998 addRepeatedCallback(server, callback, data, interval_ms, callbackId);
21999 UA_UNLOCK(&server->serviceMutex);
22000 return retval;
22001}
22002
22003UA_StatusCode
22004changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
22005 UA_Double interval_ms) {
22006 return UA_Timer_changeRepeatedCallback(t: &server->timer, callbackId,
22007 interval_ms, NULL, timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
22008}
22009
22010UA_StatusCode
22011UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
22012 UA_Double interval_ms) {
22013 UA_LOCK(&server->serviceMutex);
22014 UA_StatusCode retval =
22015 changeRepeatedCallbackInterval(server, callbackId, interval_ms);
22016 UA_UNLOCK(&server->serviceMutex);
22017 return retval;
22018}
22019
22020void
22021removeCallback(UA_Server *server, UA_UInt64 callbackId) {
22022 UA_Timer_removeCallback(t: &server->timer, callbackId);
22023}
22024
22025void
22026UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId) {
22027 UA_LOCK(&server->serviceMutex);
22028 removeCallback(server, callbackId);
22029 UA_UNLOCK(&server->serviceMutex);
22030}
22031
22032UA_StatusCode
22033UA_Server_updateCertificate(UA_Server *server,
22034 const UA_ByteString *oldCertificate,
22035 const UA_ByteString *newCertificate,
22036 const UA_ByteString *newPrivateKey,
22037 UA_Boolean closeSessions,
22038 UA_Boolean closeSecureChannels) {
22039
22040 UA_CHECK(server && oldCertificate && newCertificate && newPrivateKey,
22041 return UA_STATUSCODE_BADINTERNALERROR);
22042
22043 if(closeSessions) {
22044 session_list_entry *current;
22045 LIST_FOREACH(current, &server->sessions, pointers) {
22046 if(UA_ByteString_equal(string1: oldCertificate,
22047 string2: &current->session.header.channel->securityPolicy->localCertificate)) {
22048 UA_LOCK(&server->serviceMutex);
22049 UA_Server_removeSessionByToken(server, token: &current->session.header.authenticationToken,
22050 event: UA_DIAGNOSTICEVENT_CLOSE);
22051 UA_UNLOCK(&server->serviceMutex);
22052 }
22053 }
22054
22055 }
22056
22057 if(closeSecureChannels) {
22058 channel_entry *entry;
22059 TAILQ_FOREACH(entry, &server->channels, pointers) {
22060 if(UA_ByteString_equal(string1: &entry->channel.securityPolicy->localCertificate, string2: oldCertificate))
22061 UA_Server_closeSecureChannel(server, channel: &entry->channel, event: UA_DIAGNOSTICEVENT_CLOSE);
22062 }
22063 }
22064
22065 size_t i = 0;
22066 while(i < server->config.endpointsSize) {
22067 UA_EndpointDescription *ed = &server->config.endpoints[i];
22068 if(UA_ByteString_equal(string1: &ed->serverCertificate, string2: oldCertificate)) {
22069 UA_String_clear(p: &ed->serverCertificate);
22070 UA_String_copy(src: newCertificate, dst: &ed->serverCertificate);
22071 UA_SecurityPolicy *sp = getSecurityPolicyByUri(server,
22072 securityPolicyUri: &server->config.endpoints[i].securityPolicyUri);
22073 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
22074 sp->updateCertificateAndPrivateKey(sp, *newCertificate, *newPrivateKey);
22075 }
22076 i++;
22077 }
22078
22079 return UA_STATUSCODE_GOOD;
22080}
22081
22082/***************************/
22083/* Server lookup functions */
22084/***************************/
22085
22086UA_SecurityPolicy *
22087getSecurityPolicyByUri(const UA_Server *server, const UA_ByteString *securityPolicyUri) {
22088 for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
22089 UA_SecurityPolicy *securityPolicyCandidate = &server->config.securityPolicies[i];
22090 if(UA_ByteString_equal(string1: securityPolicyUri, string2: &securityPolicyCandidate->policyUri))
22091 return securityPolicyCandidate;
22092 }
22093 return NULL;
22094}
22095
22096#ifdef UA_ENABLE_ENCRYPTION
22097/* The local ApplicationURI has to match the certificates of the
22098 * SecurityPolicies */
22099static UA_StatusCode
22100verifyServerApplicationURI(const UA_Server *server) {
22101 const UA_String securityPolicyNoneUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None");
22102 for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
22103 UA_SecurityPolicy *sp = &server->config.securityPolicies[i];
22104 if(UA_String_equal(s1: &sp->policyUri, s2: &securityPolicyNoneUri) && (sp->localCertificate.length == 0))
22105 continue;
22106 UA_StatusCode retval = server->config.certificateVerification.
22107 verifyApplicationURI(server->config.certificateVerification.context,
22108 &sp->localCertificate,
22109 &server->config.applicationDescription.applicationUri);
22110
22111 UA_CHECK_STATUS_ERROR(retval, return retval, &server->config.logger, UA_LOGCATEGORY_SERVER,
22112 "The configured ApplicationURI \"%.*s\"does not match the "
22113 "ApplicationURI specified in the certificate for the "
22114 "SecurityPolicy %.*s",
22115 (int)server->config.applicationDescription.applicationUri.length,
22116 server->config.applicationDescription.applicationUri.data,
22117 (int)sp->policyUri.length, sp->policyUri.data);
22118 }
22119 return UA_STATUSCODE_GOOD;
22120}
22121#endif
22122
22123UA_ServerStatistics
22124UA_Server_getStatistics(UA_Server *server) {
22125 UA_ServerStatistics stat;
22126 stat.ns = server->networkStatistics;
22127 stat.scs = server->secureChannelStatistics;
22128
22129 stat.ss.currentSessionCount = server->activeSessionCount;
22130 stat.ss.cumulatedSessionCount =
22131 server->serverDiagnosticsSummary.cumulatedSessionCount;
22132 stat.ss.securityRejectedSessionCount =
22133 server->serverDiagnosticsSummary.securityRejectedSessionCount;
22134 stat.ss.rejectedSessionCount =
22135 server->serverDiagnosticsSummary.rejectedSessionCount;
22136 stat.ss.sessionTimeoutCount =
22137 server->serverDiagnosticsSummary.sessionTimeoutCount;
22138 stat.ss.sessionAbortCount =
22139 server->serverDiagnosticsSummary.sessionAbortCount;
22140
22141 return stat;
22142}
22143
22144/********************/
22145/* Main Server Loop */
22146/********************/
22147
22148#define UA_MAXTIMEOUT 50 /* Max timeout in ms between main-loop iterations */
22149
22150/* Start: Spin up the workers and the network layer and sample the server's
22151 * start time.
22152 * Iterate: Process repeated callbacks and events in the network layer. This
22153 * part can be driven from an external main-loop in an event-driven
22154 * single-threaded architecture.
22155 * Stop: Stop workers, finish all callbacks, stop the network layer, clean up */
22156
22157UA_StatusCode
22158UA_Server_run_startup(UA_Server *server) {
22159
22160#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
22161 /* Prominently warn user that fuzzing build is enabled. This will tamper with authentication tokens and other important variables
22162 * E.g. if fuzzing is enabled, and two clients are connected, subscriptions do not work properly,
22163 * since the tokens will be overridden to allow easier fuzzing. */
22164 UA_LOG_FATAL(&server->config.logger, UA_LOGCATEGORY_SERVER,
22165 "Server was built with unsafe fuzzing mode. "
22166 "This should only be used for specific fuzzing builds.");
22167#endif
22168
22169 /* ensure that the uri for ns1 is set up from the app description */
22170 setupNs1Uri(server);
22171
22172 /* write ServerArray with same ApplicationURI value as NamespaceArray */
22173 UA_StatusCode retVal =
22174 writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY,
22175 v: &server->config.applicationDescription.applicationUri,
22176 length: 1, type: &UA_TYPES[UA_TYPES_STRING]);
22177 UA_CHECK_STATUS(retVal, return retVal);
22178
22179 if(server->state > UA_SERVERLIFECYCLE_FRESH)
22180 return UA_STATUSCODE_GOOD;
22181
22182 /* At least one endpoint has to be configured */
22183 if(server->config.endpointsSize == 0) {
22184 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
22185 msg: "There has to be at least one endpoint.");
22186 }
22187
22188 /* Does the ApplicationURI match the local certificates? */
22189#ifdef UA_ENABLE_ENCRYPTION
22190 retVal = verifyServerApplicationURI(server);
22191 UA_CHECK_STATUS(retVal, return retVal);
22192#endif
22193
22194 /* Sample the start time and set it to the Server object */
22195 server->startTime = UA_DateTime_now();
22196 UA_Variant var;
22197 UA_Variant_init(p: &var);
22198 UA_Variant_setScalar(v: &var, p: &server->startTime, type: &UA_TYPES[UA_TYPES_DATETIME]);
22199 UA_Server_writeValue(server,
22200 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME),
22201 value: var);
22202
22203 /* Start the networklayers */
22204 UA_StatusCode result = UA_STATUSCODE_GOOD;
22205 for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
22206 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
22207 nl->statistics = &server->networkStatistics;
22208 result |= nl->start(nl, &server->config.logger, &server->config.customHostname);
22209 }
22210 UA_CHECK_STATUS(result, return result);
22211
22212 /* Update the application description to match the previously added
22213 * discovery urls. We can only do this after the network layer is started
22214 * since it inits the discovery url */
22215 if(server->config.applicationDescription.discoveryUrlsSize != 0) {
22216 UA_Array_delete(p: server->config.applicationDescription.discoveryUrls,
22217 size: server->config.applicationDescription.discoveryUrlsSize,
22218 type: &UA_TYPES[UA_TYPES_STRING]);
22219 server->config.applicationDescription.discoveryUrlsSize = 0;
22220 }
22221 server->config.applicationDescription.discoveryUrls = (UA_String *)
22222 UA_Array_new(size: server->config.networkLayersSize, type: &UA_TYPES[UA_TYPES_STRING]);
22223 UA_CHECK_MEM(server->config.applicationDescription.discoveryUrls,
22224 return UA_STATUSCODE_BADOUTOFMEMORY);
22225
22226 server->config.applicationDescription.discoveryUrlsSize =
22227 server->config.networkLayersSize;
22228 for(size_t i = 0; i < server->config.applicationDescription.discoveryUrlsSize; i++) {
22229 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
22230 UA_String_copy(src: &nl->discoveryUrl,
22231 dst: &server->config.applicationDescription.discoveryUrls[i]);
22232 }
22233
22234 /* Start the multicast discovery server */
22235#ifdef UA_ENABLE_DISCOVERY_MULTICAST
22236 if(server->config.mdnsEnabled)
22237 startMulticastDiscoveryServer(server);
22238#endif
22239
22240 /* Update Endpoint description */
22241 for(size_t i = 0; i < server->config.endpointsSize; ++i){
22242 UA_ApplicationDescription_clear(p: &server->config.endpoints[i].server);
22243 UA_ApplicationDescription_copy(src: &server->config.applicationDescription,
22244 dst: &server->config.endpoints[i].server);
22245 }
22246
22247 server->state = UA_SERVERLIFECYCLE_FRESH;
22248
22249 return result;
22250}
22251
22252static void
22253serverExecuteRepeatedCallback(UA_Server *server, UA_ApplicationCallback cb,
22254 void *callbackApplication, void *data) {
22255 /* Service mutex is not set inside the timer that triggers the callback */
22256 /* The following check cannot be used since another thread can take the
22257 * serviceMutex during a server_iterate_call. */
22258 //UA_LOCK_ASSERT(&server->serviceMutex, 0);
22259 cb(callbackApplication, data);
22260}
22261
22262UA_UInt16
22263UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
22264 /* Process repeated work */
22265 UA_DateTime now = UA_DateTime_nowMonotonic();
22266 UA_DateTime nextRepeated = UA_Timer_process(t: &server->timer, nowMonotonic: now,
22267 executionCallback: (UA_TimerExecutionCallback)serverExecuteRepeatedCallback, executionApplication: server);
22268 UA_DateTime latest = now + (UA_MAXTIMEOUT * UA_DATETIME_MSEC);
22269 if(nextRepeated > latest)
22270 nextRepeated = latest;
22271
22272 UA_UInt16 timeout = 0;
22273
22274 /* round always to upper value to avoid timeout to be set to 0
22275 * if(nextRepeated - now) < (UA_DATETIME_MSEC/2) */
22276 if(waitInternal)
22277 timeout = (UA_UInt16)(((nextRepeated - now) + (UA_DATETIME_MSEC - 1)) / UA_DATETIME_MSEC);
22278
22279 /* Listen on the networklayer */
22280 for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
22281 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
22282 nl->listen(nl, server, timeout);
22283 }
22284
22285#if defined(UA_ENABLE_PUBSUB_MQTT)
22286 /* Listen on the pubsublayer, but only if the yield function is set */
22287 UA_PubSubConnection *connection;
22288 TAILQ_FOREACH(connection, &server->pubSubManager.connections, listEntry){
22289 UA_PubSubConnection *ps = connection;
22290 if(ps && ps->channel->yield){
22291 ps->channel->yield(ps->channel, timeout);
22292 }
22293 }
22294#endif
22295
22296 UA_LOCK(&server->serviceMutex);
22297
22298#if defined(UA_ENABLE_DISCOVERY_MULTICAST) && (UA_MULTITHREADING < 200)
22299 if(server->config.mdnsEnabled) {
22300 /* TODO multicastNextRepeat does not consider new input data (requests)
22301 * on the socket. It will be handled on the next call. if needed, we
22302 * need to use select with timeout on the multicast socket
22303 * server->mdnsSocket (see example in mdnsd library) on higher level. */
22304 UA_DateTime multicastNextRepeat = 0;
22305 UA_StatusCode hasNext =
22306 iterateMulticastDiscoveryServer(server, &multicastNextRepeat, true);
22307 if(hasNext == UA_STATUSCODE_GOOD && multicastNextRepeat < nextRepeated)
22308 nextRepeated = multicastNextRepeat;
22309 }
22310#endif
22311
22312 UA_UNLOCK(&server->serviceMutex);
22313
22314 now = UA_DateTime_nowMonotonic();
22315 timeout = 0;
22316 if(nextRepeated > now)
22317 timeout = (UA_UInt16)((nextRepeated - now) / UA_DATETIME_MSEC);
22318 return timeout;
22319}
22320
22321UA_StatusCode
22322UA_Server_run_shutdown(UA_Server *server) {
22323 /* Stop the netowrk layer */
22324 for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
22325 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
22326 nl->stop(nl, server);
22327 }
22328
22329#ifdef UA_ENABLE_DISCOVERY_MULTICAST
22330 /* Stop multicast discovery */
22331 if(server->config.mdnsEnabled)
22332 stopMulticastDiscoveryServer(server);
22333#endif
22334
22335 return UA_STATUSCODE_GOOD;
22336}
22337
22338static UA_Boolean
22339testShutdownCondition(UA_Server *server) {
22340 if(server->endTime == 0)
22341 return false;
22342 return (UA_DateTime_now() > server->endTime);
22343}
22344
22345UA_StatusCode
22346UA_Server_run(UA_Server *server, const volatile UA_Boolean *running) {
22347 UA_StatusCode retval = UA_Server_run_startup(server);
22348 UA_CHECK_STATUS(retval, return retval);
22349
22350#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
22351 size_t loopCount = 0;
22352#endif
22353 while(!testShutdownCondition(server)) {
22354#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
22355 if(loopCount == 0) {
22356 VALGRIND_DO_LEAK_CHECK;
22357 }
22358 ++loopCount;
22359 loopCount %= UA_VALGRIND_INTERACTIVE_INTERVAL;
22360#endif
22361 UA_Server_run_iterate(server, true);
22362 if(!*running) {
22363 if(setServerShutdown(server))
22364 break;
22365 }
22366 }
22367 return UA_Server_run_shutdown(server);
22368}
22369
22370/**** amalgamated original file "/src/server/ua_server_ns0.c" ****/
22371
22372/* This Source Code Form is subject to the terms of the Mozilla Public
22373 * License, v. 2.0. If a copy of the MPL was not distributed with this
22374 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
22375 *
22376 * Copyright 2017-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
22377 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
22378 * Copyright 2017 (c) Thomas Bender
22379 * Copyright 2017 (c) Julian Grothoff
22380 * Copyright 2017 (c) Henrik Norrman
22381 * Copyright 2018 (c) Fabian Arndt, Root-Core
22382 * Copyright 2019 (c) Kalycito Infotech Private Limited
22383 * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
22384 */
22385
22386
22387
22388static UA_StatusCode
22389addNode_raw(UA_Server *server, UA_NodeClass nodeClass,
22390 UA_UInt32 nodeId, char *name, void *attributes,
22391 const UA_DataType *attributesType) {
22392 UA_AddNodesItem item;
22393 UA_AddNodesItem_init(p: &item);
22394 item.nodeClass = nodeClass;
22395 item.requestedNewNodeId.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: nodeId);
22396 item.browseName = UA_QUALIFIEDNAME(nsIndex: 0, chars: name);
22397 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes,
22398 p: attributes, type: attributesType);
22399 return AddNode_raw(server, session: &server->adminSession, NULL, item: &item, NULL);
22400}
22401
22402static UA_StatusCode
22403addNode_finish(UA_Server *server, UA_UInt32 nodeId,
22404 UA_UInt32 parentNodeId, UA_UInt32 referenceTypeId) {
22405 const UA_NodeId sourceId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: nodeId);
22406 const UA_NodeId refTypeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: referenceTypeId);
22407 const UA_ExpandedNodeId targetId = UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, identifier: parentNodeId);
22408 UA_StatusCode retval = UA_Server_addReference(server, sourceId, refTypeId, targetId, false);
22409 if(retval != UA_STATUSCODE_GOOD)
22410 return retval;
22411 return AddNode_finish(server, session: &server->adminSession, nodeId: &sourceId);
22412}
22413
22414static UA_StatusCode
22415addObjectNode(UA_Server *server, char* name, UA_UInt32 objectid,
22416 UA_UInt32 parentid, UA_UInt32 referenceid, UA_UInt32 type_id) {
22417 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
22418 object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name);
22419 return UA_Server_addObjectNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: objectid),
22420 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: parentid),
22421 referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: referenceid),
22422 browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name),
22423 typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, identifier: type_id),
22424 attr: object_attr, NULL, NULL);
22425}
22426
22427static UA_StatusCode
22428addReferenceTypeNode(UA_Server *server, char* name, char *inverseName, UA_UInt32 referencetypeid,
22429 UA_Boolean isabstract, UA_Boolean symmetric, UA_UInt32 parentid) {
22430 UA_ReferenceTypeAttributes reference_attr = UA_ReferenceTypeAttributes_default;
22431 reference_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name);
22432 reference_attr.isAbstract = isabstract;
22433 reference_attr.symmetric = symmetric;
22434 if(inverseName)
22435 reference_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: inverseName);
22436 return UA_Server_addReferenceTypeNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: referencetypeid),
22437 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: parentid), referenceTypeId: UA_NODEID_NULL,
22438 browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name), attr: reference_attr, NULL, NULL);
22439}
22440
22441/***************************/
22442/* Bootstrap NS0 hierarchy */
22443/***************************/
22444
22445/* Creates the basic nodes which are expected by the nodeset compiler to be
22446 * already created. This is necessary to reduce the dependencies for the nodeset
22447 * compiler. */
22448static UA_StatusCode
22449UA_Server_createNS0_base(UA_Server *server) {
22450 /* Bootstrap ReferenceTypes. The order of these is important for the
22451 * ReferenceTypeIndex. The ReferenceTypeIndex is created with the raw node.
22452 * The ReferenceTypeSet of subtypes for every ReferenceType is created
22453 * during the call to AddNode_finish. */
22454 UA_StatusCode ret = UA_STATUSCODE_GOOD;
22455 UA_ReferenceTypeAttributes references_attr = UA_ReferenceTypeAttributes_default;
22456 references_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "References");
22457 references_attr.isAbstract = true;
22458 references_attr.symmetric = true;
22459 references_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "References");
22460 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_REFERENCES, name: "References",
22461 attributes: &references_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
22462
22463 UA_ReferenceTypeAttributes hassubtype_attr = UA_ReferenceTypeAttributes_default;
22464 hassubtype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasSubtype");
22465 hassubtype_attr.isAbstract = false;
22466 hassubtype_attr.symmetric = false;
22467 hassubtype_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "HasSupertype");
22468 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_HASSUBTYPE, name: "HasSubtype",
22469 attributes: &hassubtype_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
22470
22471 UA_ReferenceTypeAttributes aggregates_attr = UA_ReferenceTypeAttributes_default;
22472 aggregates_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Aggregates");
22473 aggregates_attr.isAbstract = true;
22474 aggregates_attr.symmetric = false;
22475 aggregates_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "AggregatedBy");
22476 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_AGGREGATES, name: "Aggregates",
22477 attributes: &aggregates_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
22478
22479 ret |= addReferenceTypeNode(server, name: "HierarchicalReferences", NULL,
22480 UA_NS0ID_HIERARCHICALREFERENCES, true, false, UA_NS0ID_REFERENCES);
22481
22482 ret |= addReferenceTypeNode(server, name: "NonHierarchicalReferences", NULL,
22483 UA_NS0ID_NONHIERARCHICALREFERENCES, true, true, UA_NS0ID_REFERENCES);
22484
22485 ret |= addReferenceTypeNode(server, name: "HasChild", NULL, UA_NS0ID_HASCHILD,
22486 true, false, UA_NS0ID_HIERARCHICALREFERENCES);
22487
22488 ret |= addReferenceTypeNode(server, name: "Organizes", inverseName: "OrganizedBy", UA_NS0ID_ORGANIZES,
22489 false, false, UA_NS0ID_HIERARCHICALREFERENCES);
22490
22491 ret |= addReferenceTypeNode(server, name: "HasEventSource", inverseName: "EventSourceOf", UA_NS0ID_HASEVENTSOURCE,
22492 false, false, UA_NS0ID_HIERARCHICALREFERENCES);
22493
22494 ret |= addReferenceTypeNode(server, name: "HasModellingRule", inverseName: "ModellingRuleOf", UA_NS0ID_HASMODELLINGRULE,
22495 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22496
22497 ret |= addReferenceTypeNode(server, name: "HasEncoding", inverseName: "EncodingOf", UA_NS0ID_HASENCODING,
22498 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22499
22500 ret |= addReferenceTypeNode(server, name: "HasDescription", inverseName: "DescriptionOf", UA_NS0ID_HASDESCRIPTION,
22501 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22502
22503 ret |= addReferenceTypeNode(server, name: "HasTypeDefinition", inverseName: "TypeDefinitionOf", UA_NS0ID_HASTYPEDEFINITION,
22504 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22505
22506 ret |= addReferenceTypeNode(server, name: "GeneratesEvent", inverseName: "GeneratedBy", UA_NS0ID_GENERATESEVENT,
22507 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22508
22509 /* Complete bootstrap of Aggregates */
22510 ret |= addNode_finish(server, UA_NS0ID_AGGREGATES, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE);
22511
22512 /* Complete bootstrap of HasSubtype */
22513 ret |= addNode_finish(server, UA_NS0ID_HASSUBTYPE, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE);
22514
22515 ret |= addReferenceTypeNode(server, name: "HasProperty", inverseName: "PropertyOf", UA_NS0ID_HASPROPERTY,
22516 false, false, UA_NS0ID_AGGREGATES);
22517
22518 ret |= addReferenceTypeNode(server, name: "HasComponent", inverseName: "ComponentOf", UA_NS0ID_HASCOMPONENT,
22519 false, false, UA_NS0ID_AGGREGATES);
22520
22521 ret |= addReferenceTypeNode(server, name: "HasNotifier", inverseName: "NotifierOf", UA_NS0ID_HASNOTIFIER,
22522 false, false, UA_NS0ID_HASEVENTSOURCE);
22523
22524 ret |= addReferenceTypeNode(server, name: "HasOrderedComponent", inverseName: "OrderedComponentOf",
22525 UA_NS0ID_HASORDEREDCOMPONENT, false, false, UA_NS0ID_HASCOMPONENT);
22526
22527 ret |= addReferenceTypeNode(server, name: "HasInterface", inverseName: "InterfaceOf",
22528 UA_NS0ID_HASINTERFACE, false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22529
22530 /**************/
22531 /* Data Types */
22532 /**************/
22533
22534 /* Bootstrap BaseDataType */
22535 UA_DataTypeAttributes basedatatype_attr = UA_DataTypeAttributes_default;
22536 basedatatype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseDataType");
22537 basedatatype_attr.isAbstract = true;
22538 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_DATATYPE, UA_NS0ID_BASEDATATYPE, name: "BaseDataType",
22539 attributes: &basedatatype_attr, attributesType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]);
22540
22541 /*****************/
22542 /* VariableTypes */
22543 /*****************/
22544
22545 UA_VariableTypeAttributes basevar_attr = UA_VariableTypeAttributes_default;
22546 basevar_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseVariableType");
22547 basevar_attr.isAbstract = true;
22548 basevar_attr.valueRank = UA_VALUERANK_ANY;
22549 basevar_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE);
22550 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_VARIABLETYPE, UA_NS0ID_BASEVARIABLETYPE, name: "BaseVariableType",
22551 attributes: &basevar_attr, attributesType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]);
22552
22553 UA_VariableTypeAttributes bdv_attr = UA_VariableTypeAttributes_default;
22554 bdv_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseDataVariableType");
22555 bdv_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE);
22556 bdv_attr.valueRank = UA_VALUERANK_ANY;
22557 ret |= UA_Server_addVariableTypeNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATAVARIABLETYPE),
22558 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEVARIABLETYPE),
22559 referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "BaseDataVariableType"),
22560 typeDefinition: UA_NODEID_NULL, attr: bdv_attr, NULL, NULL);
22561
22562 UA_VariableTypeAttributes prop_attr = UA_VariableTypeAttributes_default;
22563 prop_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PropertyType");
22564 prop_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE);
22565 prop_attr.valueRank = UA_VALUERANK_ANY;
22566 ret |= UA_Server_addVariableTypeNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PROPERTYTYPE),
22567 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEVARIABLETYPE),
22568 referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PropertyType"),
22569 typeDefinition: UA_NODEID_NULL, attr: prop_attr, NULL, NULL);
22570
22571 /***************/
22572 /* ObjectTypes */
22573 /***************/
22574
22575 UA_ObjectTypeAttributes baseobj_attr = UA_ObjectTypeAttributes_default;
22576 baseobj_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseObjectType");
22577 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_OBJECTTYPE, UA_NS0ID_BASEOBJECTTYPE, name: "BaseObjectType",
22578 attributes: &baseobj_attr, attributesType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
22579
22580 UA_ObjectTypeAttributes folder_attr = UA_ObjectTypeAttributes_default;
22581 folder_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FolderType");
22582 ret |= UA_Server_addObjectTypeNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_FOLDERTYPE),
22583 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE),
22584 referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "FolderType"),
22585 attr: folder_attr, NULL, NULL);
22586
22587 /******************/
22588 /* Root and below */
22589 /******************/
22590
22591 ret |= addObjectNode(server, name: "Root", UA_NS0ID_ROOTFOLDER, parentid: 0, referenceid: 0, UA_NS0ID_FOLDERTYPE);
22592
22593 ret |= addObjectNode(server, name: "Objects", UA_NS0ID_OBJECTSFOLDER, UA_NS0ID_ROOTFOLDER,
22594 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22595
22596 ret |= addObjectNode(server, name: "Types", UA_NS0ID_TYPESFOLDER, UA_NS0ID_ROOTFOLDER,
22597 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22598
22599 ret |= addObjectNode(server, name: "ReferenceTypes", UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22600 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22601 ret |= addNode_finish(server, UA_NS0ID_REFERENCES, UA_NS0ID_REFERENCETYPESFOLDER,
22602 UA_NS0ID_ORGANIZES);
22603
22604 ret |= addObjectNode(server, name: "DataTypes", UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22605 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22606 ret |= addNode_finish(server, UA_NS0ID_BASEDATATYPE, UA_NS0ID_DATATYPESFOLDER,
22607 UA_NS0ID_ORGANIZES);
22608
22609 ret |= addObjectNode(server, name: "VariableTypes", UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22610 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22611 ret |= addNode_finish(server, UA_NS0ID_BASEVARIABLETYPE, UA_NS0ID_VARIABLETYPESFOLDER,
22612 UA_NS0ID_ORGANIZES);
22613
22614 ret |= addObjectNode(server, name: "ObjectTypes", UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22615 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22616 ret |= addNode_finish(server, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_OBJECTTYPESFOLDER,
22617 UA_NS0ID_ORGANIZES);
22618
22619 ret |= addObjectNode(server, name: "EventTypes", UA_NS0ID_EVENTTYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22620 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22621
22622 ret |= addObjectNode(server, name: "Views", UA_NS0ID_VIEWSFOLDER, UA_NS0ID_ROOTFOLDER,
22623 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22624
22625 /* Add BaseEventType */
22626 UA_ObjectTypeAttributes eventtype_attr = UA_ObjectTypeAttributes_default;
22627 eventtype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseEventType");
22628 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_OBJECTTYPE, UA_NS0ID_BASEEVENTTYPE, name: "BaseEventType",
22629 attributes: &eventtype_attr, attributesType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
22630 ret |= addNode_finish(server, UA_NS0ID_BASEEVENTTYPE, UA_NS0ID_EVENTTYPESFOLDER,
22631 UA_NS0ID_ORGANIZES);
22632
22633 if(ret != UA_STATUSCODE_GOOD)
22634 ret = UA_STATUSCODE_BADINTERNALERROR;
22635
22636 return ret;
22637}
22638
22639/****************/
22640/* Data Sources */
22641/****************/
22642
22643static UA_StatusCode
22644readStatus(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22645 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp,
22646 const UA_NumericRange *range, UA_DataValue *value) {
22647 if(range) {
22648 value->hasStatus = true;
22649 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22650 return UA_STATUSCODE_GOOD;
22651 }
22652
22653 if(sourceTimestamp) {
22654 value->hasSourceTimestamp = true;
22655 value->sourceTimestamp = UA_DateTime_now();
22656 }
22657
22658 void *data = NULL;
22659
22660 UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC);
22661
22662 switch(nodeId->identifier.numeric) {
22663 case UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN: {
22664 UA_UInt32 *shutdown = UA_UInt32_new();
22665 if(!shutdown)
22666 return UA_STATUSCODE_BADOUTOFMEMORY;
22667 if(server->endTime != 0)
22668 *shutdown = (UA_UInt32)((server->endTime - UA_DateTime_now()) / UA_DATETIME_SEC);
22669 value->value.data = shutdown;
22670 value->value.type = &UA_TYPES[UA_TYPES_UINT32];
22671 value->hasValue = true;
22672 return UA_STATUSCODE_GOOD;
22673 }
22674
22675 case UA_NS0ID_SERVER_SERVERSTATUS_STATE: {
22676 UA_ServerState *state = UA_ServerState_new();
22677 if(!state)
22678 return UA_STATUSCODE_BADOUTOFMEMORY;
22679 if(server->endTime != 0)
22680 *state = UA_SERVERSTATE_SHUTDOWN;
22681 value->value.data = state;
22682 value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATE];
22683 value->hasValue = true;
22684 return UA_STATUSCODE_GOOD;
22685 }
22686
22687 case UA_NS0ID_SERVER_SERVERSTATUS: {
22688 UA_ServerStatusDataType *statustype = UA_ServerStatusDataType_new();
22689 if(!statustype)
22690 return UA_STATUSCODE_BADOUTOFMEMORY;
22691 statustype->startTime = server->startTime;
22692 statustype->currentTime = UA_DateTime_now();
22693
22694 statustype->state = UA_SERVERSTATE_RUNNING;
22695 statustype->secondsTillShutdown = 0;
22696 if(server->endTime != 0) {
22697 statustype->state = UA_SERVERSTATE_SHUTDOWN;
22698 statustype->secondsTillShutdown = (UA_UInt32)
22699 ((server->endTime - UA_DateTime_now()) / UA_DATETIME_SEC);
22700 }
22701
22702 value->value.data = statustype;
22703 value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
22704 value->hasValue = true;
22705 return UA_BuildInfo_copy(src: &server->config.buildInfo, dst: &statustype->buildInfo);
22706 }
22707
22708 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO:
22709 value->value.type = &UA_TYPES[UA_TYPES_BUILDINFO];
22710 data = &server->config.buildInfo;
22711 break;
22712
22713 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI:
22714 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22715 data = &server->config.buildInfo.productUri;
22716 break;
22717
22718 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME:
22719 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22720 data = &server->config.buildInfo.manufacturerName;
22721 break;
22722
22723 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME:
22724 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22725 data = &server->config.buildInfo.productName;
22726 break;
22727
22728 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION:
22729 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22730 data = &server->config.buildInfo.softwareVersion;
22731 break;
22732
22733 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER:
22734 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22735 data = &server->config.buildInfo.buildNumber;
22736 break;
22737
22738 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE:
22739 value->value.type = &UA_TYPES[UA_TYPES_DATETIME];
22740 data = &server->config.buildInfo.buildDate;
22741 break;
22742
22743 default:
22744 value->hasStatus = true;
22745 value->status = UA_STATUSCODE_BADINTERNALERROR;
22746 return UA_STATUSCODE_GOOD;
22747 }
22748
22749 value->value.data = UA_new(type: value->value.type);
22750 if(!value->value.data) {
22751 value->value.type = NULL;
22752 return UA_STATUSCODE_BADOUTOFMEMORY;
22753 }
22754
22755 value->hasValue = true;
22756 return UA_copy(src: data, dst: value->value.data, type: value->value.type);
22757}
22758
22759#ifdef UA_GENERATED_NAMESPACE_ZERO
22760static UA_StatusCode
22761readServiceLevel(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22762 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp,
22763 const UA_NumericRange *range, UA_DataValue *value) {
22764 if(range) {
22765 value->hasStatus = true;
22766 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22767 return UA_STATUSCODE_GOOD;
22768 }
22769
22770 value->value.type = &UA_TYPES[UA_TYPES_BYTE];
22771 value->value.arrayLength = 0;
22772 UA_Byte *byte = UA_Byte_new();
22773 *byte = 255;
22774 value->value.data = byte;
22775 value->value.arrayDimensionsSize = 0;
22776 value->value.arrayDimensions = NULL;
22777 value->hasValue = true;
22778 if(includeSourceTimeStamp) {
22779 value->hasSourceTimestamp = true;
22780 value->sourceTimestamp = UA_DateTime_now();
22781 }
22782 return UA_STATUSCODE_GOOD;
22783}
22784
22785static UA_StatusCode
22786readAuditing(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22787 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp,
22788 const UA_NumericRange *range, UA_DataValue *value) {
22789 if(range) {
22790 value->hasStatus = true;
22791 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22792 return UA_STATUSCODE_GOOD;
22793 }
22794
22795 value->value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
22796 value->value.arrayLength = 0;
22797 UA_Boolean *boolean = UA_Boolean_new();
22798 *boolean = false;
22799 value->value.data = boolean;
22800 value->value.arrayDimensionsSize = 0;
22801 value->value.arrayDimensions = NULL;
22802 value->hasValue = true;
22803 if(includeSourceTimeStamp) {
22804 value->hasSourceTimestamp = true;
22805 value->sourceTimestamp = UA_DateTime_now();
22806 }
22807 return UA_STATUSCODE_GOOD;
22808}
22809#endif
22810
22811static UA_StatusCode
22812readNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22813 const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp,
22814 const UA_NumericRange *range,
22815 UA_DataValue *value) {
22816 /* ensure that the uri for ns1 is set up from the app description */
22817 setupNs1Uri(server);
22818
22819 if(range) {
22820 value->hasStatus = true;
22821 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22822 return UA_STATUSCODE_GOOD;
22823 }
22824 UA_StatusCode retval;
22825 retval = UA_Variant_setArrayCopy(v: &value->value, array: server->namespaces,
22826 arraySize: server->namespacesSize, type: &UA_TYPES[UA_TYPES_STRING]);
22827 if(retval != UA_STATUSCODE_GOOD)
22828 return retval;
22829 value->hasValue = true;
22830 if(includeSourceTimeStamp) {
22831 value->hasSourceTimestamp = true;
22832 value->sourceTimestamp = UA_DateTime_now();
22833 }
22834 return UA_STATUSCODE_GOOD;
22835}
22836
22837static UA_StatusCode
22838writeNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22839 const UA_NodeId *nodeid, void *nodeContext, const UA_NumericRange *range,
22840 const UA_DataValue *value) {
22841 /* Check the data type */
22842 if(!value->hasValue ||
22843 value->value.type != &UA_TYPES[UA_TYPES_STRING])
22844 return UA_STATUSCODE_BADTYPEMISMATCH;
22845
22846 /* Check that the variant is not empty */
22847 if(!value->value.data)
22848 return UA_STATUSCODE_BADTYPEMISMATCH;
22849
22850 /* TODO: Writing with a range is not implemented */
22851 if(range)
22852 return UA_STATUSCODE_BADINTERNALERROR;
22853
22854 UA_String *newNamespaces = (UA_String*)value->value.data;
22855 size_t newNamespacesSize = value->value.arrayLength;
22856
22857 /* Test if we append to the existing namespaces */
22858 if(newNamespacesSize <= server->namespacesSize)
22859 return UA_STATUSCODE_BADTYPEMISMATCH;
22860
22861 /* ensure that the uri for ns1 is set up from the app description */
22862 setupNs1Uri(server);
22863
22864 /* Test if the existing namespaces are unchanged */
22865 for(size_t i = 0; i < server->namespacesSize; ++i) {
22866 if(!UA_String_equal(s1: &server->namespaces[i], s2: &newNamespaces[i]))
22867 return UA_STATUSCODE_BADINTERNALERROR;
22868 }
22869
22870 /* Add namespaces */
22871 for(size_t i = server->namespacesSize; i < newNamespacesSize; ++i)
22872 addNamespace(server, name: newNamespaces[i]);
22873 return UA_STATUSCODE_GOOD;
22874}
22875
22876static UA_StatusCode
22877readCurrentTime(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22878 const UA_NodeId *nodeid, void *nodeContext, UA_Boolean sourceTimeStamp,
22879 const UA_NumericRange *range, UA_DataValue *value) {
22880 if(range) {
22881 value->hasStatus = true;
22882 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22883 return UA_STATUSCODE_GOOD;
22884 }
22885 UA_DateTime currentTime = UA_DateTime_now();
22886 UA_StatusCode retval = UA_Variant_setScalarCopy(v: &value->value, p: &currentTime,
22887 type: &UA_TYPES[UA_TYPES_DATETIME]);
22888 if(retval != UA_STATUSCODE_GOOD)
22889 return retval;
22890 value->hasValue = true;
22891 if(sourceTimeStamp) {
22892 value->hasSourceTimestamp = true;
22893 value->sourceTimestamp = currentTime;
22894 }
22895 return UA_STATUSCODE_GOOD;
22896}
22897
22898#ifdef UA_GENERATED_NAMESPACE_ZERO
22899static UA_StatusCode
22900readMinSamplingInterval(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22901 const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp,
22902 const UA_NumericRange *range,
22903 UA_DataValue *value) {
22904 if(range) {
22905 value->hasStatus = true;
22906 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22907 return UA_STATUSCODE_GOOD;
22908 }
22909
22910 UA_StatusCode retval;
22911 UA_Duration minInterval;
22912#ifdef UA_ENABLE_SUBSCRIPTIONS
22913 minInterval = server->config.samplingIntervalLimits.min;
22914#else
22915 minInterval = 0.0;
22916#endif
22917 retval = UA_Variant_setScalarCopy(v: &value->value, p: &minInterval, type: &UA_TYPES[UA_TYPES_DURATION]);
22918 if(retval != UA_STATUSCODE_GOOD)
22919 return retval;
22920 value->hasValue = true;
22921 if(includeSourceTimeStamp) {
22922 value->hasSourceTimestamp = true;
22923 value->sourceTimestamp = UA_DateTime_now();
22924 }
22925 return UA_STATUSCODE_GOOD;
22926}
22927#endif
22928
22929#if defined(UA_GENERATED_NAMESPACE_ZERO) && defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
22930static UA_StatusCode
22931readMonitoredItems(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22932 const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId,
22933 void *objectContext, size_t inputSize, const UA_Variant *input,
22934 size_t outputSize, UA_Variant *output) {
22935 /* Return two empty arrays by default */
22936 UA_Variant_setArray(v: &output[0], array: UA_Array_new(size: 0, type: &UA_TYPES[UA_TYPES_UINT32]),
22937 arraySize: 0, type: &UA_TYPES[UA_TYPES_UINT32]);
22938 UA_Variant_setArray(v: &output[1], array: UA_Array_new(size: 0, type: &UA_TYPES[UA_TYPES_UINT32]),
22939 arraySize: 0, type: &UA_TYPES[UA_TYPES_UINT32]);
22940
22941 /* Get the Session */
22942 UA_LOCK(&server->serviceMutex);
22943 UA_Session *session = UA_Server_getSessionById(server, sessionId);
22944 if(!session) {
22945 UA_UNLOCK(&server->serviceMutex);
22946 return UA_STATUSCODE_BADINTERNALERROR;
22947 }
22948 if(inputSize == 0 || !input[0].data) {
22949 UA_UNLOCK(&server->serviceMutex);
22950 return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
22951 }
22952
22953 /* Get the Subscription */
22954 UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data));
22955 UA_Subscription *subscription = UA_Server_getSubscriptionById(server, subscriptionId);
22956 if(!subscription) {
22957 UA_UNLOCK(&server->serviceMutex);
22958 return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
22959 }
22960
22961 /* The Subscription is not attached to this Session */
22962 if(subscription->session != session) {
22963 UA_UNLOCK(&server->serviceMutex);
22964 return UA_STATUSCODE_BADUSERACCESSDENIED;
22965 }
22966
22967 /* Count the MonitoredItems */
22968 UA_UInt32 sizeOfOutput = 0;
22969 UA_MonitoredItem* monitoredItem;
22970 LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
22971 ++sizeOfOutput;
22972 }
22973 if(sizeOfOutput == 0) {
22974 UA_UNLOCK(&server->serviceMutex);
22975 return UA_STATUSCODE_GOOD;
22976 }
22977
22978 /* Allocate the output arrays */
22979 UA_UInt32 *clientHandles = (UA_UInt32*)
22980 UA_Array_new(size: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]);
22981 if(!clientHandles) {
22982 UA_UNLOCK(&server->serviceMutex);
22983 return UA_STATUSCODE_BADOUTOFMEMORY;
22984 }
22985 UA_UInt32 *serverHandles = (UA_UInt32*)
22986 UA_Array_new(size: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]);
22987 if(!serverHandles) {
22988 UA_UNLOCK(&server->serviceMutex);
22989 UA_free(ptr: clientHandles);
22990 return UA_STATUSCODE_BADOUTOFMEMORY;
22991 }
22992
22993 /* Fill the array */
22994 UA_UInt32 i = 0;
22995 LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
22996 clientHandles[i] = monitoredItem->parameters.clientHandle;
22997 serverHandles[i] = monitoredItem->monitoredItemId;
22998 ++i;
22999 }
23000 UA_Variant_setArray(v: &output[0], array: serverHandles, arraySize: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]);
23001 UA_Variant_setArray(v: &output[1], array: clientHandles, arraySize: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]);
23002
23003 UA_UNLOCK(&server->serviceMutex);
23004 return UA_STATUSCODE_GOOD;
23005}
23006#endif /* defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) */
23007
23008UA_StatusCode
23009writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
23010 size_t length, const UA_DataType *type) {
23011 UA_Variant var;
23012 UA_Variant_init(p: &var);
23013 UA_Variant_setArray(v: &var, array: v, arraySize: length, type);
23014 return UA_Server_writeValue(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: id), value: var);
23015}
23016
23017#ifndef UA_GENERATED_NAMESPACE_ZERO
23018static UA_StatusCode
23019addVariableNode(UA_Server *server, char* name, UA_UInt32 variableid,
23020 UA_UInt32 parentid, UA_UInt32 referenceid,
23021 UA_Int32 valueRank, UA_UInt32 dataType) {
23022 UA_VariableAttributes attr = UA_VariableAttributes_default;
23023 attr.displayName = UA_LOCALIZEDTEXT("", name);
23024 attr.dataType = UA_NODEID_NUMERIC(0, dataType);
23025 attr.valueRank = valueRank;
23026 attr.accessLevel = UA_ACCESSLEVELMASK_READ;
23027 return UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(0, variableid),
23028 UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NUMERIC(0, referenceid),
23029 UA_QUALIFIEDNAME(0, name),
23030 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
23031 attr, NULL, NULL);
23032}
23033
23034/* A minimal server object that is not complete and does not use the mandated
23035 * references to a server type. To be used on very constrained devices. */
23036static UA_StatusCode
23037UA_Server_minimalServerObject(UA_Server *server) {
23038 /* Server */
23039 UA_StatusCode retval = addObjectNode(server, "Server", UA_NS0ID_SERVER, UA_NS0ID_OBJECTSFOLDER,
23040 UA_NS0ID_ORGANIZES, UA_NS0ID_BASEOBJECTTYPE);
23041
23042 /* Use a valuerank of -2 for now. The array is added later on and the valuerank set to 1. */
23043 retval |= addVariableNode(server, "ServerArray", UA_NS0ID_SERVER_SERVERARRAY,
23044 UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY,
23045 UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE);
23046
23047 retval |= addVariableNode(server, "NamespaceArray", UA_NS0ID_SERVER_NAMESPACEARRAY,
23048 UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY,
23049 UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE);
23050
23051 retval |= addVariableNode(server, "ServerStatus", UA_NS0ID_SERVER_SERVERSTATUS,
23052 UA_NS0ID_SERVER, UA_NS0ID_HASCOMPONENT,
23053 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23054
23055 retval |= addVariableNode(server, "CurrentTime", UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME,
23056 UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
23057 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23058
23059 retval |= addVariableNode(server, "State", UA_NS0ID_SERVER_SERVERSTATUS_STATE,
23060 UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
23061 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23062
23063 retval |= addVariableNode(server, "BuildInfo", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO,
23064 UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
23065 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23066
23067 retval |= addVariableNode(server, "ProductUri", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI,
23068 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23069 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23070
23071 retval |= addVariableNode(server, "ManufacturerName",
23072 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME,
23073 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23074 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23075
23076 retval |= addVariableNode(server, "ProductName",
23077 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME,
23078 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23079 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23080
23081 retval |= addVariableNode(server, "SoftwareVersion",
23082 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION,
23083 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23084 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23085
23086 retval |= addVariableNode(server, "BuildNumber",
23087 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER,
23088 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23089 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23090
23091 retval |= addVariableNode(server, "BuildDate",
23092 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE,
23093 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23094 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23095
23096 return retval;
23097}
23098
23099#else
23100
23101static UA_StatusCode
23102writeNs0Variable(UA_Server *server, UA_UInt32 id, void *v, const UA_DataType *type) {
23103 UA_Variant var;
23104 UA_Variant_init(p: &var);
23105 UA_Variant_setScalar(v: &var, p: v, type);
23106 return UA_Server_writeValue(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: id), value: var);
23107}
23108
23109static void
23110addModellingRules(UA_Server *server) {
23111 /* Test if the ModellingRules folder was added. (Only for the full ns0.) */
23112 UA_NodeClass mrnc = UA_NODECLASS_UNSPECIFIED;
23113 UA_StatusCode retval = UA_Server_readNodeClass(server,
23114 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23115 outNodeClass: &mrnc);
23116 if(retval != UA_STATUSCODE_GOOD)
23117 return;
23118
23119 /* Add ExposesItsArray */
23120 UA_Server_addReference(server,
23121 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23122 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23123 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_EXPOSESITSARRAY),
23124 true);
23125
23126 /* Add Mandatory */
23127 UA_Server_addReference(server,
23128 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23129 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23130 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_MANDATORY),
23131 true);
23132
23133
23134 /* Add MandatoryPlaceholder */
23135 UA_Server_addReference(server,
23136 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23137 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23138 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_MANDATORYPLACEHOLDER),
23139 true);
23140
23141 /* Add Optional */
23142 UA_Server_addReference(server,
23143 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23144 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23145 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_OPTIONAL),
23146 true);
23147
23148 /* Add OptionalPlaceholder */
23149 UA_Server_addReference(server,
23150 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23151 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23152 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_OPTIONALPLACEHOLDER),
23153 true);
23154}
23155
23156#endif
23157
23158/* Initialize the nodeset 0 by using the generated code of the nodeset compiler.
23159 * This also initialized the data sources for various variables, such as for
23160 * example server time. */
23161UA_StatusCode
23162UA_Server_initNS0(UA_Server *server) {
23163 /* Initialize base nodes which are always required an cannot be created
23164 * through the NS compiler */
23165 server->bootstrapNS0 = true;
23166 UA_StatusCode retVal = UA_Server_createNS0_base(server);
23167
23168#ifdef UA_GENERATED_NAMESPACE_ZERO
23169 /* Load nodes and references generated from the XML ns0 definition */
23170 retVal |= namespace0_generated(server);
23171#else
23172 /* Create a minimal server object */
23173 retVal |= UA_Server_minimalServerObject(server);
23174#endif
23175
23176 server->bootstrapNS0 = false;
23177
23178 if(retVal != UA_STATUSCODE_GOOD) {
23179 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
23180 msg: "Initialization of Namespace 0 failed with %s. "
23181 "See previous outputs for any error messages.",
23182 UA_StatusCode_name(code: retVal));
23183 return UA_STATUSCODE_BADINTERNALERROR;
23184 }
23185
23186 /* NamespaceArray */
23187 UA_DataSource namespaceDataSource = {readNamespaces, writeNamespaces};
23188 retVal |= UA_Server_setVariableNode_dataSource(server,
23189 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY),
23190 dataSource: namespaceDataSource);
23191 retVal |= UA_Server_writeValueRank(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY), valueRank: 1);
23192
23193 /* ServerArray */
23194 retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY,
23195 v: &server->config.applicationDescription.applicationUri,
23196 length: 1, type: &UA_TYPES[UA_TYPES_STRING]);
23197 retVal |= UA_Server_writeValueRank(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERARRAY), valueRank: 1);
23198
23199 /* ServerStatus */
23200 UA_DataSource serverStatus = {readStatus, NULL};
23201 retVal |= UA_Server_setVariableNode_dataSource(server,
23202 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS), dataSource: serverStatus);
23203
23204 /* StartTime will be sampled in UA_Server_run_startup()*/
23205
23206 /* CurrentTime */
23207 UA_DataSource currentTime = {readCurrentTime, NULL};
23208 UA_NodeId currTime = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
23209 retVal |= UA_Server_setVariableNode_dataSource(server, nodeId: currTime, dataSource: currentTime);
23210 retVal |= UA_Server_writeMinimumSamplingInterval(server, nodeId: currTime, miniumSamplingInterval: 100.0);
23211
23212 /* State */
23213 retVal |= UA_Server_setVariableNode_dataSource(server,
23214 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STATE),
23215 dataSource: serverStatus);
23216
23217 /* BuildInfo */
23218 retVal |= UA_Server_setVariableNode_dataSource(server,
23219 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), dataSource: serverStatus);
23220
23221 /* BuildInfo - ProductUri */
23222 retVal |= UA_Server_setVariableNode_dataSource(server,
23223 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI),
23224 dataSource: serverStatus);
23225
23226 /* BuildInfo - ManufacturerName */
23227 retVal |= UA_Server_setVariableNode_dataSource(server,
23228 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME),
23229 dataSource: serverStatus);
23230
23231 /* BuildInfo - ProductName */
23232 retVal |= UA_Server_setVariableNode_dataSource(server,
23233 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME),
23234 dataSource: serverStatus);
23235
23236 /* BuildInfo - SoftwareVersion */
23237 retVal |= UA_Server_setVariableNode_dataSource(server,
23238 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION),
23239 dataSource: serverStatus);
23240
23241 /* BuildInfo - BuildNumber */
23242 retVal |= UA_Server_setVariableNode_dataSource(server,
23243 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
23244 dataSource: serverStatus);
23245
23246 /* BuildInfo - BuildDate */
23247 retVal |= UA_Server_setVariableNode_dataSource(server,
23248 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE),
23249 dataSource: serverStatus);
23250
23251#ifdef UA_GENERATED_NAMESPACE_ZERO
23252
23253 /* SecondsTillShutdown */
23254 retVal |= UA_Server_setVariableNode_dataSource(server,
23255 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN),
23256 dataSource: serverStatus);
23257
23258 /* ShutDownReason */
23259 UA_LocalizedText shutdownReason;
23260 UA_LocalizedText_init(p: &shutdownReason);
23261 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON,
23262 v: &shutdownReason, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
23263
23264 /* ServiceLevel */
23265 UA_DataSource serviceLevel = {readServiceLevel, NULL};
23266 retVal |= UA_Server_setVariableNode_dataSource(server,
23267 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVICELEVEL), dataSource: serviceLevel);
23268
23269 /* ServerDiagnostics - EnabledFlag */
23270#ifdef UA_ENABLE_DIAGNOSTICS
23271 UA_Boolean enabledFlag = true;
23272#else
23273 UA_Boolean enabledFlag = false;
23274#endif
23275 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG,
23276 v: &enabledFlag, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23277
23278 /* According to Specification part-5 - pg.no-11(PDF pg.no-29), when the ServerDiagnostics is disabled the client
23279 * may modify the value of enabledFlag=true in the server. By default, this node have CurrentRead/Write access.
23280 * In CTT, Subscription_Minimum_1/002.js test will modify the above flag. This will not be a problem when build
23281 * configuration is set at UA_NAMESPACE_ZERO="REDUCED" as NodeIds will not be present. When UA_NAMESPACE_ZERO="FULL",
23282 * the test will fail. Hence made the NodeId as read only */
23283 retVal |= UA_Server_writeAccessLevel(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG),
23284 UA_ACCESSLEVELMASK_READ);
23285
23286 /* Auditing */
23287 UA_DataSource auditing = {readAuditing, NULL};
23288 retVal |= UA_Server_setVariableNode_dataSource(server,
23289 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_AUDITING), dataSource: auditing);
23290
23291 /* Redundancy Support */
23292 UA_RedundancySupport redundancySupport = UA_REDUNDANCYSUPPORT_NONE;
23293 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANCYSUPPORT,
23294 v: &redundancySupport, type: &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
23295
23296 /* Remove unused subtypes of ServerRedundancy */
23297 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_CURRENTSERVERID), true);
23298 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANTSERVERARRAY), true);
23299 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_SERVERURIARRAY), true);
23300 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_SERVERNETWORKGROUPS), true);
23301
23302 /* ServerCapabilities - LocaleIdArray */
23303 UA_LocaleId locale_en = UA_STRING(chars: "en");
23304 retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY,
23305 v: &locale_en, length: 1, type: &UA_TYPES[UA_TYPES_LOCALEID]);
23306
23307 /* ServerCapabilities - MaxBrowseContinuationPoints */
23308 UA_UInt16 maxBrowseContinuationPoints = UA_MAXCONTINUATIONPOINTS;
23309 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS,
23310 v: &maxBrowseContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]);
23311
23312 /* ServerProfileArray */
23313 UA_String profileArray[3];
23314 UA_UInt16 profileArraySize = 0;
23315#define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING(x)
23316 ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/MicroEmbeddedDevice");
23317#ifdef UA_ENABLE_NODEMANAGEMENT
23318 ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement");
23319#endif
23320#ifdef UA_ENABLE_METHODCALLS
23321 ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods");
23322#endif
23323 retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY,
23324 v: profileArray, length: profileArraySize, type: &UA_TYPES[UA_TYPES_STRING]);
23325
23326 /* ServerCapabilities - MaxQueryContinuationPoints */
23327 UA_UInt16 maxQueryContinuationPoints = 0;
23328 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS,
23329 v: &maxQueryContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]);
23330
23331 /* ServerCapabilities - MaxHistoryContinuationPoints */
23332 UA_UInt16 maxHistoryContinuationPoints = 0;
23333 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS,
23334 v: &maxHistoryContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]);
23335
23336 /* ServerCapabilities - MinSupportedSampleRate */
23337 UA_DataSource samplingInterval = {readMinSamplingInterval, NULL};
23338 retVal |= UA_Server_setVariableNode_dataSource(server,
23339 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE),
23340 dataSource: samplingInterval);
23341
23342 /* ServerCapabilities - OperationLimits - MaxNodesPerRead */
23343 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD,
23344 v: &server->config.maxNodesPerRead, type: &UA_TYPES[UA_TYPES_UINT32]);
23345
23346 /* ServerCapabilities - OperationLimits - maxNodesPerWrite */
23347 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE,
23348 v: &server->config.maxNodesPerWrite, type: &UA_TYPES[UA_TYPES_UINT32]);
23349
23350 /* ServerCapabilities - OperationLimits - MaxNodesPerMethodCall */
23351 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL,
23352 v: &server->config.maxNodesPerMethodCall, type: &UA_TYPES[UA_TYPES_UINT32]);
23353
23354 /* ServerCapabilities - OperationLimits - MaxNodesPerBrowse */
23355 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE,
23356 v: &server->config.maxNodesPerBrowse, type: &UA_TYPES[UA_TYPES_UINT32]);
23357
23358 /* ServerCapabilities - OperationLimits - MaxNodesPerRegisterNodes */
23359 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES,
23360 v: &server->config.maxNodesPerRegisterNodes, type: &UA_TYPES[UA_TYPES_UINT32]);
23361
23362 /* ServerCapabilities - OperationLimits - MaxNodesPerTranslateBrowsePathsToNodeIds */
23363 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS,
23364 v: &server->config.maxNodesPerTranslateBrowsePathsToNodeIds, type: &UA_TYPES[UA_TYPES_UINT32]);
23365
23366 /* ServerCapabilities - OperationLimits - MaxNodesPerNodeManagement */
23367 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT,
23368 v: &server->config.maxNodesPerNodeManagement, type: &UA_TYPES[UA_TYPES_UINT32]);
23369
23370 /* ServerCapabilities - OperationLimits - MaxMonitoredItemsPerCall */
23371 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL,
23372 v: &server->config.maxMonitoredItemsPerCall, type: &UA_TYPES[UA_TYPES_UINT32]);
23373
23374 /* Remove unused operation limit components */
23375 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADDATA), true);
23376 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADEVENTS), true);
23377 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEDATA), true);
23378 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEEVENTS), true);
23379 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_ROLESET), true);
23380 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXSTRINGLENGTH), true);
23381 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXARRAYLENGTH), true);
23382 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBYTESTRINGLENGTH), true);
23383
23384 /* Remove not supported server configurations */
23385 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_ESTIMATEDRETURNTIME), true);
23386 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_LOCALTIME), true);
23387 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_REQUESTSERVERSTATECHANGE), true);
23388 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_RESENDDATA), true);
23389 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVERCONFIGURATION), true);
23390 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SETSUBSCRIPTIONDURABLE), true);
23391
23392#ifdef UA_ENABLE_DIAGNOSTICS
23393 /* ServerDiagnostics - ServerDiagnosticsSummary */
23394 UA_DataSource serverDiagSummary = {readDiagnostics, NULL};
23395 retVal |= UA_Server_setVariableNode_dataSource(server,
23396 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), serverDiagSummary);
23397
23398 /* ServerDiagnostics - ServerDiagnosticsSummary - ServerViewCount */
23399 retVal |= UA_Server_setVariableNode_dataSource(server,
23400 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT), serverDiagSummary);
23401
23402 /* ServerDiagnostics - ServerDiagnosticsSummary - CurrentSessionCount */
23403 retVal |= UA_Server_setVariableNode_dataSource(server,
23404 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT), serverDiagSummary);
23405
23406 /* ServerDiagnostics - ServerDiagnosticsSummary - CumulatedSessionCount */
23407 retVal |= UA_Server_setVariableNode_dataSource(server,
23408 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT), serverDiagSummary);
23409
23410 /* ServerDiagnostics - ServerDiagnosticsSummary - SecurityRejectedSessionCount */
23411 retVal |= UA_Server_setVariableNode_dataSource(server,
23412 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT), serverDiagSummary);
23413
23414 /* ServerDiagnostics - ServerDiagnosticsSummary - RejectedSessionCount */
23415 retVal |= UA_Server_setVariableNode_dataSource(server,
23416 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT), serverDiagSummary);
23417
23418 /* ServerDiagnostics - ServerDiagnosticsSummary - SessionTimeoutCount */
23419 retVal |= UA_Server_setVariableNode_dataSource(server,
23420 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT), serverDiagSummary);
23421
23422 /* ServerDiagnostics - ServerDiagnosticsSummary - SessionAbortCount */
23423 retVal |= UA_Server_setVariableNode_dataSource(server,
23424 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT), serverDiagSummary);
23425
23426 /* ServerDiagnostics - ServerDiagnosticsSummary - CurrentSubscriptionCount */
23427 retVal |= UA_Server_setVariableNode_dataSource(server,
23428 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT), serverDiagSummary);
23429
23430 /* ServerDiagnostics - ServerDiagnosticsSummary - CumulatedSubscriptionCount */
23431 retVal |= UA_Server_setVariableNode_dataSource(server,
23432 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT), serverDiagSummary);
23433
23434 /* ServerDiagnostics - ServerDiagnosticsSummary - PublishingIntervalCount */
23435 retVal |= UA_Server_setVariableNode_dataSource(server,
23436 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT), serverDiagSummary);
23437
23438 /* ServerDiagnostics - ServerDiagnosticsSummary - SecurityRejectedRequestsCount */
23439 retVal |= UA_Server_setVariableNode_dataSource(server,
23440 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT), serverDiagSummary);
23441
23442 /* ServerDiagnostics - ServerDiagnosticsSummary - RejectedRequestsCount */
23443 retVal |= UA_Server_setVariableNode_dataSource(server,
23444 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT), serverDiagSummary);
23445
23446 /* ServerDiagnostics - SubscriptionDiagnosticsArray */
23447#ifdef UA_ENABLE_SUBSCRIPTIONS
23448 UA_DataSource serverSubDiagSummary = {readSubscriptionDiagnosticsArray, NULL};
23449 retVal |= UA_Server_setVariableNode_dataSource(server,
23450 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), serverSubDiagSummary);
23451#endif
23452
23453 /* ServerDiagnostics - SessionDiagnosticsSummary - SessionDiagnosticsArray */
23454 UA_DataSource sessionDiagSummary = {readSessionDiagnosticsArray, NULL};
23455 retVal |= UA_Server_setVariableNode_dataSource(server,
23456 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONDIAGNOSTICSARRAY), sessionDiagSummary);
23457
23458 /* ServerDiagnostics - SessionDiagnosticsSummary - SessionSecurityDiagnosticsArray */
23459 UA_DataSource sessionSecDiagSummary = {readSessionSecurityDiagnostics, NULL};
23460 retVal |= UA_Server_setVariableNode_dataSource(server,
23461 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONSECURITYDIAGNOSTICSARRAY), sessionSecDiagSummary);
23462
23463#else
23464 /* Removing these NodeIds make Server Object to be non-complaint with UA
23465 * 1.03 in CTT (Base Inforamtion/Base Info Core Structure/ 001.js) In the
23466 * 1.04 specification this has been resolved by allowing to remove these
23467 * static nodes as well */
23468 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SAMPLINGINTERVALDIAGNOSTICSARRAY), true);
23469 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY), true);
23470 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), true);
23471 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), true);
23472#endif
23473
23474#ifndef UA_ENABLE_PUBSUB
23475 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE), true);
23476#endif
23477
23478#ifndef UA_ENABLE_HISTORIZING
23479 UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HISTORYSERVERCAPABILITIES), true);
23480#else
23481 /* ServerCapabilities - HistoryServerCapabilities - AccessHistoryDataCapability */
23482 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYDATACAPABILITY,
23483 v: &server->config.accessHistoryDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23484
23485 /* ServerCapabilities - HistoryServerCapabilities - MaxReturnDataValues */
23486 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNDATAVALUES,
23487 v: &server->config.maxReturnDataValues, type: &UA_TYPES[UA_TYPES_UINT32]);
23488
23489 /* ServerCapabilities - HistoryServerCapabilities - AccessHistoryEventsCapability */
23490 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYEVENTSCAPABILITY,
23491 v: &server->config.accessHistoryEventsCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23492
23493 /* ServerCapabilities - HistoryServerCapabilities - MaxReturnEventValues */
23494 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNEVENTVALUES,
23495 v: &server->config.maxReturnEventValues, type: &UA_TYPES[UA_TYPES_UINT32]);
23496
23497 /* ServerCapabilities - HistoryServerCapabilities - InsertDataCapability */
23498 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTDATACAPABILITY,
23499 v: &server->config.insertDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23500
23501 /* ServerCapabilities - HistoryServerCapabilities - InsertEventCapability */
23502 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTEVENTCAPABILITY,
23503 v: &server->config.insertEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23504
23505 /* ServerCapabilities - HistoryServerCapabilities - InsertAnnotationsCapability */
23506 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTANNOTATIONCAPABILITY,
23507 v: &server->config.insertAnnotationsCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23508
23509 /* ServerCapabilities - HistoryServerCapabilities - ReplaceDataCapability */
23510 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEDATACAPABILITY,
23511 v: &server->config.replaceDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23512
23513 /* ServerCapabilities - HistoryServerCapabilities - ReplaceEventCapability */
23514 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEEVENTCAPABILITY,
23515 v: &server->config.replaceEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23516
23517 /* ServerCapabilities - HistoryServerCapabilities - UpdateDataCapability */
23518 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEDATACAPABILITY,
23519 v: &server->config.updateDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23520
23521 /* ServerCapabilities - HistoryServerCapabilities - UpdateEventCapability */
23522 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEEVENTCAPABILITY,
23523 v: &server->config.updateEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23524
23525 /* ServerCapabilities - HistoryServerCapabilities - DeleteRawCapability */
23526 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETERAWCAPABILITY,
23527 v: &server->config.deleteRawCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23528
23529 /* ServerCapabilities - HistoryServerCapabilities - DeleteEventCapability */
23530 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEEVENTCAPABILITY,
23531 v: &server->config.deleteEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23532
23533 /* ServerCapabilities - HistoryServerCapabilities - DeleteAtTimeDataCapability */
23534 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEATTIMECAPABILITY,
23535 v: &server->config.deleteAtTimeDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23536#endif
23537
23538#if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
23539 retVal |= UA_Server_setMethodNodeCallback(server,
23540 methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_GETMONITOREDITEMS), methodCallback: readMonitoredItems);
23541#endif
23542
23543 /* The HasComponent references to the ModellingRules are not part of the
23544 * Nodeset2.xml. So we add the references manually. */
23545 addModellingRules(server);
23546
23547#endif /* UA_GENERATED_NAMESPACE_ZERO */
23548
23549 if(retVal != UA_STATUSCODE_GOOD) {
23550 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
23551 msg: "Initialization of Namespace 0 (after bootstrapping) "
23552 "failed with %s. See previous outputs for any error messages.",
23553 UA_StatusCode_name(code: retVal));
23554 return UA_STATUSCODE_BADINTERNALERROR;
23555 }
23556 return UA_STATUSCODE_GOOD;
23557}
23558
23559/**** amalgamated original file "/src/server/ua_server_ns0_diagnostics.c" ****/
23560
23561/* This Source Code Form is subject to the terms of the Mozilla Public
23562 * License, v. 2.0. If a copy of the MPL was not distributed with this
23563 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
23564 *
23565 * Copyright 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
23566 */
23567
23568
23569#ifdef UA_ENABLE_DIAGNOSTICS
23570
23571static UA_Boolean
23572equalBrowseName(UA_String *bn, char *n) {
23573 UA_String name = UA_STRING(n);
23574 return UA_String_equal(bn, &name);
23575}
23576
23577#ifdef UA_ENABLE_SUBSCRIPTIONS
23578
23579/****************************/
23580/* Subscription Diagnostics */
23581/****************************/
23582
23583static void
23584fillSubscriptionDiagnostics(UA_Subscription *sub,
23585 UA_SubscriptionDiagnosticsDataType *diag) {
23586 UA_NodeId_copy(&sub->session->sessionId, &diag->sessionId); /* ignore status */
23587 diag->subscriptionId = sub->subscriptionId;
23588 diag->priority = sub->priority;
23589 diag->publishingInterval = sub->publishingInterval;
23590 diag->maxKeepAliveCount = sub->maxKeepAliveCount;
23591 diag->maxLifetimeCount = sub->lifeTimeCount;
23592 diag->maxNotificationsPerPublish = sub->notificationsPerPublish;
23593 diag->publishingEnabled = sub->publishingEnabled;
23594 diag->modifyCount = sub->modifyCount;
23595 diag->enableCount = sub->enableCount;
23596 diag->disableCount = sub->disableCount;
23597 diag->republishRequestCount = sub->republishRequestCount;
23598 diag->republishMessageRequestCount =
23599 sub->republishRequestCount; /* Always equal to the previous republishRequestCount */
23600 diag->republishMessageCount = sub->republishMessageCount;
23601 diag->transferRequestCount = sub->transferRequestCount;
23602 diag->transferredToAltClientCount = sub->transferredToAltClientCount;
23603 diag->transferredToSameClientCount = sub->transferredToSameClientCount;
23604 diag->publishRequestCount = sub->publishRequestCount;
23605 diag->dataChangeNotificationsCount = sub->dataChangeNotificationsCount;
23606 diag->eventNotificationsCount = sub->eventNotificationsCount;
23607 diag->notificationsCount = sub->notificationsCount;
23608 diag->latePublishRequestCount = sub->latePublishRequestCount;
23609 diag->currentKeepAliveCount = sub->currentKeepAliveCount;
23610 diag->currentLifetimeCount = sub->currentLifetimeCount;
23611 diag->unacknowledgedMessageCount = (UA_UInt32)sub->retransmissionQueueSize;
23612 diag->discardedMessageCount = sub->discardedMessageCount;
23613 diag->monitoredItemCount = sub->monitoredItemsSize;
23614 diag->monitoringQueueOverflowCount = sub->monitoringQueueOverflowCount;
23615 diag->nextSequenceNumber = sub->nextSequenceNumber;
23616 diag->eventQueueOverFlowCount = sub->eventQueueOverFlowCount;
23617
23618 /* Count the disabled MonitoredItems */
23619 UA_MonitoredItem *mon;
23620 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
23621 if(mon->monitoringMode == UA_MONITORINGMODE_DISABLED)
23622 diag->disabledMonitoredItemCount++;
23623 }
23624}
23625
23626/* The node context points to the subscription */
23627static UA_StatusCode
23628readSubscriptionDiagnostics(UA_Server *server,
23629 const UA_NodeId *sessionId, void *sessionContext,
23630 const UA_NodeId *nodeId, void *nodeContext,
23631 UA_Boolean sourceTimestamp,
23632 const UA_NumericRange *range, UA_DataValue *value) {
23633 /* Check the Subscription pointer */
23634 UA_Subscription *sub = (UA_Subscription*)nodeContext;
23635 if(!sub)
23636 return UA_STATUSCODE_BADINTERNALERROR;
23637
23638 /* Read the BrowseName */
23639 UA_QualifiedName bn;
23640 UA_StatusCode res = readWithReadValue(server, nodeId, UA_ATTRIBUTEID_BROWSENAME, &bn);
23641 if(res != UA_STATUSCODE_GOOD)
23642 return res;
23643
23644 /* Set the value */
23645 UA_SubscriptionDiagnosticsDataType sddt;
23646 UA_SubscriptionDiagnosticsDataType_init(&sddt);
23647 fillSubscriptionDiagnostics(sub, &sddt);
23648
23649 char memberName[128];
23650 memcpy(memberName, bn.name.data, bn.name.length);
23651 memberName[bn.name.length] = 0;
23652
23653 size_t memberOffset;
23654 const UA_DataType *memberType;
23655 UA_Boolean isArray;
23656 UA_Boolean found =
23657 UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE],
23658 memberName, &memberOffset, &memberType, &isArray);
23659 if(!found) {
23660 /* Not the member, but the main subscription diagnostics variable... */
23661 memberOffset = 0;
23662 memberType = &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE];
23663 }
23664
23665 void *content = (void*)(((uintptr_t)&sddt) + memberOffset);
23666 res = UA_Variant_setScalarCopy(&value->value, content, memberType);
23667 if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
23668 value->hasValue = true;
23669
23670 UA_SubscriptionDiagnosticsDataType_clear(&sddt);
23671 UA_QualifiedName_clear(&bn);
23672 return res;
23673}
23674
23675/* If the nodeContext == NULL, return all subscriptions in the server.
23676 * Otherwise only for the current session. */
23677UA_StatusCode
23678readSubscriptionDiagnosticsArray(UA_Server *server,
23679 const UA_NodeId *sessionId, void *sessionContext,
23680 const UA_NodeId *nodeId, void *nodeContext,
23681 UA_Boolean sourceTimestamp,
23682 const UA_NumericRange *range, UA_DataValue *value) {
23683 /* Get the current session */
23684 size_t sdSize = 0;
23685 UA_Session *session = NULL;
23686 session_list_entry *sentry;
23687 if(nodeContext) {
23688 session = UA_Server_getSessionById(server, sessionId);
23689 if(!session)
23690 return UA_STATUSCODE_BADINTERNALERROR;
23691 sdSize = session->subscriptionsSize;
23692 } else {
23693 LIST_FOREACH(sentry, &server->sessions, pointers) {
23694 sdSize += sentry->session.subscriptionsSize;
23695 }
23696 }
23697
23698 /* Allocate the output array */
23699 UA_SubscriptionDiagnosticsDataType *sd = (UA_SubscriptionDiagnosticsDataType*)
23700 UA_Array_new(sdSize, &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]);
23701 if(!sd)
23702 return UA_STATUSCODE_BADOUTOFMEMORY;
23703
23704 /* Collect the statistics */
23705 size_t i = 0;
23706 UA_Subscription *sub;
23707 if(session) {
23708 TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
23709 fillSubscriptionDiagnostics(sub, &sd[i]);
23710 i++;
23711 }
23712 } else {
23713 LIST_FOREACH(sentry, &server->sessions, pointers) {
23714 TAILQ_FOREACH(sub, &sentry->session.subscriptions, sessionListEntry) {
23715 fillSubscriptionDiagnostics(sub, &sd[i]);
23716 i++;
23717 }
23718 }
23719 }
23720
23721 /* Set the output */
23722 value->hasValue = true;
23723 UA_Variant_setArray(&value->value, sd, sdSize,
23724 &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]);
23725 return UA_STATUSCODE_GOOD;
23726}
23727
23728void
23729createSubscriptionObject(UA_Server *server, UA_Session *session,
23730 UA_Subscription *sub) {
23731 UA_ExpandedNodeId *children = NULL;
23732 size_t childrenSize = 0;
23733 UA_ReferenceTypeSet refTypes;
23734 UA_NodeId hasComponent = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
23735
23736 char subIdStr[32];
23737 snprintf(subIdStr, 32, "%u", sub->subscriptionId);
23738
23739 /* Find the NodeId of the SubscriptionDiagnosticsArray */
23740 UA_BrowsePath bp;
23741 UA_BrowsePath_init(&bp);
23742 bp.startingNode = sub->session->sessionId;
23743 UA_RelativePathElement rpe[1];
23744 memset(rpe, 0, sizeof(UA_RelativePathElement) * 1);
23745 rpe[0].targetName = UA_QUALIFIEDNAME(0, "SubscriptionDiagnosticsArray");
23746 bp.relativePath.elements = rpe;
23747 bp.relativePath.elementsSize = 1;
23748 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, &bp);
23749 if(bpr.targetsSize < 1)
23750 return;
23751
23752 /* Create an object for the subscription. Instantiates all the mandatory
23753 * children. */
23754 UA_VariableAttributes var_attr = UA_VariableAttributes_default;
23755 var_attr.displayName.text = UA_STRING(subIdStr);
23756 var_attr.dataType = UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE].typeId;
23757 UA_NodeId refId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
23758 UA_QualifiedName browseName = UA_QUALIFIEDNAME(0, subIdStr);
23759 UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SUBSCRIPTIONDIAGNOSTICSTYPE);
23760 UA_NodeId objId = UA_NODEID_NUMERIC(1, 0); /* 0 => assign a random free id */
23761 UA_StatusCode res = addNode(server, UA_NODECLASS_VARIABLE,
23762 &objId,
23763 &bpr.targets[0].targetId.nodeId /* parent */,
23764 &refId, browseName, &typeId,
23765 (UA_NodeAttributes*)&var_attr,
23766 &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, &objId);
23767 UA_CHECK_STATUS(res, goto cleanup);
23768
23769 /* Add a second reference from the overall SubscriptionDiagnosticsArray variable */
23770 const UA_NodeId subDiagArray =
23771 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY);
23772 res = addRef(server, session, &subDiagArray, &refId, &objId, true);
23773
23774 /* Get all children (including the variable itself) and set the contenxt + callback */
23775 res = referenceTypeIndices(server, &hasComponent, &refTypes, false);
23776 if(res != UA_STATUSCODE_GOOD)
23777 goto cleanup;
23778 res = browseRecursive(server, 1, &objId,
23779 UA_BROWSEDIRECTION_FORWARD, &refTypes,
23780 UA_NODECLASS_VARIABLE, true, &childrenSize, &children);
23781 if(res != UA_STATUSCODE_GOOD)
23782 goto cleanup;
23783
23784 /* Add the callback to all variables */
23785 UA_DataSource subDiagSource = {readSubscriptionDiagnostics, NULL};
23786 for(size_t i = 0; i < childrenSize; i++) {
23787 setVariableNode_dataSource(server, children[i].nodeId, subDiagSource);
23788 setNodeContext(server, children[i].nodeId, sub);
23789 }
23790
23791 UA_Array_delete(children, childrenSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
23792
23793 cleanup:
23794 UA_BrowsePathResult_clear(&bpr);
23795 if(res != UA_STATUSCODE_GOOD) {
23796 UA_LOG_WARNING_SESSION(&server->config.logger, session,
23797 "Creating the subscription diagnostics object failed "
23798 "with StatusCode %s", UA_StatusCode_name(res));
23799 }
23800}
23801
23802#endif /* UA_ENABLE_SUBSCRIPTIONS */
23803
23804/***********************/
23805/* Session Diagnostics */
23806/***********************/
23807
23808static void
23809setSessionDiagnostics(UA_Session *session, UA_SessionDiagnosticsDataType *sd) {
23810 UA_SessionDiagnosticsDataType_copy(&session->diagnostics, sd);
23811 UA_NodeId_copy(&session->sessionId, &sd->sessionId);
23812 UA_String_copy(&session->sessionName, &sd->sessionName);
23813 UA_ApplicationDescription_copy(&session->clientDescription,
23814 &sd->clientDescription);
23815 sd->maxResponseMessageSize = session->maxResponseMessageSize;
23816#ifdef UA_ENABLE_SUBSCRIPTIONS
23817 sd->currentPublishRequestsInQueue = (UA_UInt32)session->responseQueueSize;
23818#endif
23819 sd->actualSessionTimeout = session->timeout;
23820
23821 /* Set LocaleIds */
23822 UA_StatusCode res =
23823 UA_Array_copy(session->localeIds, session->localeIdsSize,
23824 (void **)&sd->localeIds, &UA_TYPES[UA_TYPES_STRING]);
23825 if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
23826 sd->localeIdsSize = session->localeIdsSize;
23827
23828 /* Set Subscription diagnostics */
23829#ifdef UA_ENABLE_SUBSCRIPTIONS
23830 sd->currentSubscriptionsCount = (UA_UInt32)session->subscriptionsSize;
23831
23832 UA_Subscription *sub;
23833 TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
23834 sd->currentMonitoredItemsCount += (UA_UInt32)sub->monitoredItemsSize;
23835 }
23836#endif
23837}
23838
23839UA_StatusCode
23840readSessionDiagnosticsArray(UA_Server *server,
23841 const UA_NodeId *sessionId, void *sessionContext,
23842 const UA_NodeId *nodeId, void *nodeContext,
23843 UA_Boolean sourceTimestamp,
23844 const UA_NumericRange *range, UA_DataValue *value) {
23845 /* Allocate the output array */
23846 UA_SessionDiagnosticsDataType *sd = (UA_SessionDiagnosticsDataType*)
23847 UA_Array_new(server->sessionCount,
23848 &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]);
23849 if(!sd)
23850 return UA_STATUSCODE_BADOUTOFMEMORY;
23851
23852 /* Collect the statistics */
23853 size_t i = 0;
23854 session_list_entry *session;
23855 LIST_FOREACH(session, &server->sessions, pointers) {
23856 setSessionDiagnostics(&session->session, &sd[i]);
23857 i++;
23858 }
23859
23860 /* Set the output */
23861 value->hasValue = true;
23862 UA_Variant_setArray(&value->value, sd, server->sessionCount,
23863 &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]);
23864 return UA_STATUSCODE_GOOD;
23865}
23866
23867static void
23868setSessionSecurityDiagnostics(UA_Session *session,
23869 UA_SessionSecurityDiagnosticsDataType *sd) {
23870 UA_SessionSecurityDiagnosticsDataType_copy(&session->securityDiagnostics, sd);
23871 UA_NodeId_copy(&session->sessionId, &sd->sessionId);
23872 UA_SecureChannel *channel = session->header.channel;
23873 if(channel) {
23874 UA_ByteString_copy(&channel->remoteCertificate, &sd->clientCertificate);
23875 UA_String_copy(&channel->securityPolicy->policyUri, &sd->securityPolicyUri);
23876 sd->securityMode = channel->securityMode;
23877 sd->encoding = UA_STRING_ALLOC("UA Binary"); /* The only one atm */
23878 sd->transportProtocol = UA_STRING_ALLOC("opc.tcp"); /* The only one atm */
23879 }
23880}
23881
23882static UA_StatusCode
23883readSessionDiagnostics(UA_Server *server,
23884 const UA_NodeId *sessionId, void *sessionContext,
23885 const UA_NodeId *nodeId, void *nodeContext,
23886 UA_Boolean sourceTimestamp,
23887 const UA_NumericRange *range, UA_DataValue *value) {
23888 /* Get the Session */
23889 UA_Session *session = UA_Server_getSessionById(server, sessionId);
23890 if(!session)
23891 return UA_STATUSCODE_BADINTERNALERROR;
23892
23893 /* Read the BrowseName */
23894 UA_QualifiedName bn;
23895 UA_StatusCode res = readWithReadValue(server, nodeId, UA_ATTRIBUTEID_BROWSENAME, &bn);
23896 if(res != UA_STATUSCODE_GOOD)
23897 return res;
23898
23899 union {
23900 UA_SessionDiagnosticsDataType sddt;
23901 UA_SessionSecurityDiagnosticsDataType ssddt;
23902 } data;
23903 void *content;
23904 UA_Boolean isArray = false;
23905 const UA_DataType *type = NULL;
23906 UA_Boolean securityDiagnostics = false;
23907
23908 char memberName[128];
23909 size_t memberOffset;
23910 UA_Boolean found;
23911
23912 if(equalBrowseName(&bn.name, "SubscriptionDiagnosticsArray")) {
23913 /* Reuse the datasource callback. Forward a non-null nodeContext to
23914 * indicate that we want to see only the subscriptions for the current
23915 * session. */
23916 res = readSubscriptionDiagnosticsArray(server, sessionId, sessionContext,
23917 nodeId, (void*)0x01,
23918 sourceTimestamp, range, value);
23919 goto cleanup;
23920 } else if(equalBrowseName(&bn.name, "SessionDiagnostics")) {
23921 setSessionDiagnostics(session, &data.sddt);
23922 content = &data.sddt;
23923 type = &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE];
23924 goto set_value;
23925 } else if(equalBrowseName(&bn.name, "SessionSecurityDiagnostics")) {
23926 setSessionSecurityDiagnostics(session, &data.ssddt);
23927 securityDiagnostics = true;
23928 content = &data.ssddt;
23929 type = &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE];
23930 goto set_value;
23931 }
23932
23933 /* Try to find the member in SessionDiagnosticsDataType and
23934 * SessionSecurityDiagnosticsDataType */
23935 memcpy(memberName, bn.name.data, bn.name.length);
23936 memberName[bn.name.length] = 0;
23937 found = UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE],
23938 memberName, &memberOffset, &type, &isArray);
23939 if(found) {
23940 setSessionDiagnostics(session, &data.sddt);
23941 content = (void*)(((uintptr_t)&data.sddt) + memberOffset);
23942 } else {
23943 found = UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE],
23944 memberName, &memberOffset, &type, &isArray);
23945 if(!found) {
23946 res = UA_STATUSCODE_BADNOTIMPLEMENTED;
23947 goto cleanup;
23948 }
23949 setSessionSecurityDiagnostics(session, &data.ssddt);
23950 securityDiagnostics = true;
23951 content = (void*)(((uintptr_t)&data.ssddt) + memberOffset);
23952 }
23953
23954 set_value:
23955 if(!isArray) {
23956 res = UA_Variant_setScalarCopy(&value->value, content, type);
23957 } else {
23958 size_t len = *(size_t*)content;
23959 content = (void*)(((uintptr_t)content) + sizeof(size_t));
23960 res = UA_Variant_setArrayCopy(&value->value, content, len, type);
23961 }
23962 if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
23963 value->hasValue = true;
23964
23965 if(securityDiagnostics)
23966 UA_SessionSecurityDiagnosticsDataType_clear(&data.ssddt);
23967 else
23968 UA_SessionDiagnosticsDataType_clear(&data.sddt);
23969
23970 cleanup:
23971 UA_QualifiedName_clear(&bn);
23972 return res;
23973}
23974
23975UA_StatusCode
23976readSessionSecurityDiagnostics(UA_Server *server,
23977 const UA_NodeId *sessionId, void *sessionContext,
23978 const UA_NodeId *nodeId, void *nodeContext,
23979 UA_Boolean sourceTimestamp,
23980 const UA_NumericRange *range, UA_DataValue *value) {
23981 /* Allocate the output array */
23982 UA_SessionSecurityDiagnosticsDataType *sd = (UA_SessionSecurityDiagnosticsDataType*)
23983 UA_Array_new(server->sessionCount,
23984 &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]);
23985 if(!sd)
23986 return UA_STATUSCODE_BADOUTOFMEMORY;
23987
23988 /* Collect the statistics */
23989 size_t i = 0;
23990 session_list_entry *session;
23991 LIST_FOREACH(session, &server->sessions, pointers) {
23992 setSessionSecurityDiagnostics(&session->session, &sd[i]);
23993 i++;
23994 }
23995
23996 /* Set the output */
23997 value->hasValue = true;
23998 UA_Variant_setArray(&value->value, sd, server->sessionCount,
23999 &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]);
24000 return UA_STATUSCODE_GOOD;
24001}
24002
24003void
24004createSessionObject(UA_Server *server, UA_Session *session) {
24005 UA_ExpandedNodeId *children = NULL;
24006 size_t childrenSize = 0;
24007 UA_ReferenceTypeSet refTypes;
24008 UA_NodeId hasComponent = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
24009
24010 /* Create an object for the session. Instantiates all the mandatory children. */
24011 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
24012 object_attr.displayName.text = session->sessionName;
24013 UA_NodeId parentId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY);
24014 UA_NodeId refId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
24015 UA_QualifiedName browseName = UA_QUALIFIEDNAME(0, "");
24016 browseName.name = session->sessionName; /* shallow copy */
24017 UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SESSIONDIAGNOSTICSOBJECTTYPE);
24018 UA_StatusCode res = addNode(server, UA_NODECLASS_OBJECT,
24019 &session->sessionId, &parentId, &refId, browseName, &typeId,
24020 (UA_NodeAttributes*)&object_attr,
24021 &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], NULL, NULL);
24022 if(res != UA_STATUSCODE_GOOD)
24023 goto cleanup;
24024
24025 /* Recursively browse all children */
24026 res = referenceTypeIndices(server, &hasComponent, &refTypes, false);
24027 if(res != UA_STATUSCODE_GOOD)
24028 goto cleanup;
24029 res = browseRecursive(server, 1, &session->sessionId,
24030 UA_BROWSEDIRECTION_FORWARD, &refTypes,
24031 UA_NODECLASS_VARIABLE, false, &childrenSize, &children);
24032 if(res != UA_STATUSCODE_GOOD)
24033 goto cleanup;
24034
24035 /* Add the callback to all variables */
24036 UA_DataSource sessionDiagSource = {readSessionDiagnostics, NULL};
24037 for(size_t i = 0; i < childrenSize; i++) {
24038 setVariableNode_dataSource(server, children[i].nodeId, sessionDiagSource);
24039 }
24040
24041 cleanup:
24042 if(res != UA_STATUSCODE_GOOD) {
24043 UA_LOG_WARNING_SESSION(&server->config.logger, session,
24044 "Creating the session diagnostics object failed "
24045 "with StatusCode %s", UA_StatusCode_name(res));
24046 }
24047 UA_Array_delete(children, childrenSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
24048}
24049
24050/***************************/
24051/* Server-Wide Diagnostics */
24052/***************************/
24053
24054UA_StatusCode
24055readDiagnostics(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
24056 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp,
24057 const UA_NumericRange *range, UA_DataValue *value) {
24058 if(range) {
24059 value->hasStatus = true;
24060 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
24061 return UA_STATUSCODE_GOOD;
24062 }
24063
24064 if(sourceTimestamp) {
24065 value->hasSourceTimestamp = true;
24066 value->sourceTimestamp = UA_DateTime_now();
24067 }
24068
24069 UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC);
24070
24071 void *data = NULL;
24072 const UA_DataType *type = &UA_TYPES[UA_TYPES_UINT32]; /* Default */
24073
24074 switch(nodeId->identifier.numeric) {
24075 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY:
24076 server->serverDiagnosticsSummary.currentSessionCount =
24077 server->activeSessionCount;
24078 data = &server->serverDiagnosticsSummary;
24079 type = &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE];
24080 break;
24081 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT:
24082 data = &server->serverDiagnosticsSummary.serverViewCount;
24083 break;
24084 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT:
24085 data = &server->activeSessionCount;
24086 break;
24087 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT:
24088 data = &server->serverDiagnosticsSummary.cumulatedSessionCount;
24089 break;
24090 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT:
24091 data = &server->serverDiagnosticsSummary.securityRejectedSessionCount;
24092 break;
24093 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT:
24094 data = &server->serverDiagnosticsSummary.rejectedSessionCount;
24095 break;
24096 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT:
24097 data = &server->serverDiagnosticsSummary.sessionTimeoutCount;
24098 break;
24099 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT:
24100 data = &server->serverDiagnosticsSummary.sessionAbortCount;
24101 break;
24102 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT:
24103 data = &server->serverDiagnosticsSummary.currentSubscriptionCount;
24104 break;
24105 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT:
24106 data = &server->serverDiagnosticsSummary.cumulatedSubscriptionCount;
24107 break;
24108 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT:
24109 data = &server->serverDiagnosticsSummary.publishingIntervalCount;
24110 break;
24111 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT:
24112 data = &server->serverDiagnosticsSummary.securityRejectedRequestsCount;
24113 break;
24114 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT:
24115 data = &server->serverDiagnosticsSummary.rejectedRequestsCount;
24116 break;
24117 default:
24118 return UA_STATUSCODE_BADINTERNALERROR;
24119 }
24120
24121 UA_StatusCode res = UA_Variant_setScalarCopy(&value->value, data, type);
24122 if(res == UA_STATUSCODE_GOOD)
24123 value->hasValue = true;
24124 return res;
24125}
24126
24127#endif /* UA_ENABLE_DIAGNOSTICS */
24128
24129/**** amalgamated original file "/src/server/ua_server_config.c" ****/
24130
24131/* This Source Code Form is subject to the terms of the Mozilla Public
24132 * License, v. 2.0. If a copy of the MPL was not distributed with this
24133 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
24134 *
24135 * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
24136 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
24137 */
24138
24139
24140void
24141UA_ServerConfig_clean(UA_ServerConfig *config) {
24142 if(!config)
24143 return;
24144
24145 /* Server Description */
24146 UA_BuildInfo_clear(p: &config->buildInfo);
24147 UA_ApplicationDescription_clear(p: &config->applicationDescription);
24148#ifdef UA_ENABLE_DISCOVERY_MULTICAST
24149 UA_MdnsDiscoveryConfiguration_clear(&config->mdnsConfig);
24150 UA_String_clear(&config->mdnsInterfaceIP);
24151# if !defined(UA_HAS_GETIFADDR)
24152 if (config->mdnsIpAddressListSize) {
24153 UA_free(config->mdnsIpAddressList);
24154 }
24155# endif
24156#endif
24157
24158 /* Custom DataTypes */
24159 /* nothing to do */
24160
24161 /* Networking */
24162 for(size_t i = 0; i < config->networkLayersSize; ++i)
24163 config->networkLayers[i].clear(&config->networkLayers[i]);
24164 UA_free(ptr: config->networkLayers);
24165 config->networkLayers = NULL;
24166 config->networkLayersSize = 0;
24167 UA_String_clear(p: &config->customHostname);
24168 config->customHostname = UA_STRING_NULL;
24169
24170 for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
24171 UA_SecurityPolicy *policy = &config->securityPolicies[i];
24172 policy->clear(policy);
24173 }
24174 UA_free(ptr: config->securityPolicies);
24175 config->securityPolicies = NULL;
24176 config->securityPoliciesSize = 0;
24177
24178 for(size_t i = 0; i < config->endpointsSize; ++i)
24179 UA_EndpointDescription_clear(p: &config->endpoints[i]);
24180
24181 UA_free(ptr: config->endpoints);
24182 config->endpoints = NULL;
24183 config->endpointsSize = 0;
24184
24185 /* Nodestore */
24186 if(config->nodestore.context && config->nodestore.clear) {
24187 config->nodestore.clear(config->nodestore.context);
24188 config->nodestore.context = NULL;
24189 }
24190
24191 /* Certificate Validation */
24192 if(config->certificateVerification.clear)
24193 config->certificateVerification.clear(&config->certificateVerification);
24194
24195 /* Access Control */
24196 if(config->accessControl.clear)
24197 config->accessControl.clear(&config->accessControl);
24198
24199 /* Historical data */
24200#ifdef UA_ENABLE_HISTORIZING
24201 if(config->historyDatabase.clear)
24202 config->historyDatabase.clear(&config->historyDatabase);
24203#endif
24204
24205 /* Logger */
24206 if(config->logger.clear)
24207 config->logger.clear(config->logger.context);
24208 config->logger.log = NULL;
24209 config->logger.clear = NULL;
24210
24211#ifdef UA_ENABLE_PUBSUB
24212#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
24213 if(config->pubSubConfig.securityPolicies != NULL) {
24214 for(size_t i = 0; i < config->pubSubConfig.securityPoliciesSize; i++) {
24215 config->pubSubConfig.securityPolicies[i].clear(&config->pubSubConfig.securityPolicies[i]);
24216 }
24217 UA_free(config->pubSubConfig.securityPolicies);
24218 config->pubSubConfig.securityPolicies = NULL;
24219 config->pubSubConfig.securityPoliciesSize = 0;
24220 }
24221#endif
24222#endif /* UA_ENABLE_PUBSUB */
24223}
24224
24225#ifdef UA_ENABLE_PUBSUB
24226/* Add a pubsubTransportLayer to the configuration. Memory is reallocated on
24227 * demand. */
24228UA_StatusCode
24229UA_ServerConfig_addPubSubTransportLayer(UA_ServerConfig *config,
24230 UA_PubSubTransportLayer pubsubTransportLayer) {
24231 UA_PubSubTransportLayer *tmpLayers = (UA_PubSubTransportLayer*)
24232 UA_realloc(config->pubSubConfig.transportLayers,
24233 sizeof(UA_PubSubTransportLayer) *
24234 (config->pubSubConfig.transportLayersSize + 1));
24235 if(tmpLayers == NULL)
24236 return UA_STATUSCODE_BADOUTOFMEMORY;
24237
24238 config->pubSubConfig.transportLayers = tmpLayers;
24239 config->pubSubConfig.transportLayers[config->pubSubConfig.transportLayersSize] = pubsubTransportLayer;
24240 config->pubSubConfig.transportLayersSize++;
24241 return UA_STATUSCODE_GOOD;
24242}
24243#endif /* UA_ENABLE_PUBSUB */
24244
24245/**** amalgamated original file "/src/server/ua_server_binary.c" ****/
24246
24247/* This Source Code Form is subject to the terms of the Mozilla Public
24248 * License, v. 2.0. If a copy of the MPL was not distributed with this
24249 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
24250 *
24251 * Copyright 2014-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
24252 * Copyright 2014-2016 (c) Sten Grüner
24253 * Copyright 2014-2015, 2017 (c) Florian Palm
24254 * Copyright 2015-2016 (c) Chris Iatrou
24255 * Copyright 2015-2016 (c) Oleksiy Vasylyev
24256 * Copyright 2016 (c) Joakim L. Gilje
24257 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
24258 * Copyright 2016 (c) TorbenD
24259 * Copyright 2017 (c) frax2222
24260 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
24261 * Copyright 2019 (c) Kalycito Infotech Private Limited
24262 */
24263
24264
24265
24266#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
24267// store the authentication token and session ID so we can help fuzzing by setting
24268// these values in the next request automatically
24269UA_NodeId unsafe_fuzz_authenticationToken = {0, UA_NODEIDTYPE_NUMERIC, {0}};
24270#endif
24271
24272#ifdef UA_DEBUG_DUMP_PKGS_FILE
24273void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection,
24274 UA_ByteString *messageBuffer);
24275#endif
24276
24277/********************/
24278/* Helper Functions */
24279/********************/
24280
24281UA_StatusCode
24282sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId,
24283 UA_UInt32 requestHandle, UA_StatusCode statusCode) {
24284 UA_ServiceFault response;
24285 UA_ServiceFault_init(p: &response);
24286 UA_ResponseHeader *responseHeader = &response.responseHeader;
24287 responseHeader->requestHandle = requestHandle;
24288 responseHeader->timestamp = UA_DateTime_now();
24289 responseHeader->serviceResult = statusCode;
24290
24291 UA_LOG_DEBUG(logger: channel->securityPolicy->logger, category: UA_LOGCATEGORY_SERVER,
24292 msg: "Sending response for RequestId %u with ServiceResult %s",
24293 (unsigned)requestId, UA_StatusCode_name(code: statusCode));
24294
24295 /* Send error message. Message type is MSG and not ERR, since we are on a
24296 * SecureChannel! */
24297 return UA_SecureChannel_sendSymmetricMessage(channel, requestId,
24298 messageType: UA_MESSAGETYPE_MSG, payload: &response,
24299 payloadType: &UA_TYPES[UA_TYPES_SERVICEFAULT]);
24300}
24301
24302/* This is not an ERR message, the connection is not closed afterwards */
24303static UA_StatusCode
24304decodeHeaderSendServiceFault(UA_SecureChannel *channel, const UA_ByteString *msg,
24305 size_t offset, const UA_DataType *responseType,
24306 UA_UInt32 requestId, UA_StatusCode error) {
24307 UA_RequestHeader requestHeader;
24308 UA_StatusCode retval =
24309 UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &requestHeader,
24310 type: &UA_TYPES[UA_TYPES_REQUESTHEADER], NULL);
24311 if(retval != UA_STATUSCODE_GOOD)
24312 return retval;
24313 retval = sendServiceFault(channel, requestId, requestHandle: requestHeader.requestHandle, statusCode: error);
24314 UA_RequestHeader_clear(p: &requestHeader);
24315 return retval;
24316}
24317
24318/* The counterOffset is the offset of the UA_ServiceCounterDataType for the
24319 * service in the UA_ SessionDiagnosticsDataType. */
24320#ifdef UA_ENABLE_DIAGNOSTICS
24321#define UA_SERVICECOUNTER_OFFSET(X) \
24322 *counterOffset = offsetof(UA_SessionDiagnosticsDataType, X)
24323#else
24324#define UA_SERVICECOUNTER_OFFSET(X)
24325#endif
24326
24327static void
24328getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
24329 const UA_DataType **responseType, UA_Service *service,
24330 UA_Boolean *requiresSession, size_t *counterOffset) {
24331 switch(requestTypeId) {
24332 case UA_NS0ID_GETENDPOINTSREQUEST_ENCODING_DEFAULTBINARY:
24333 *service = (UA_Service)Service_GetEndpoints;
24334 *requestType = &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST];
24335 *responseType = &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE];
24336 *requiresSession = false;
24337 break;
24338 case UA_NS0ID_FINDSERVERSREQUEST_ENCODING_DEFAULTBINARY:
24339 *service = (UA_Service)Service_FindServers;
24340 *requestType = &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST];
24341 *responseType = &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE];
24342 *requiresSession = false;
24343 break;
24344#ifdef UA_ENABLE_DISCOVERY
24345# ifdef UA_ENABLE_DISCOVERY_MULTICAST
24346 case UA_NS0ID_FINDSERVERSONNETWORKREQUEST_ENCODING_DEFAULTBINARY:
24347 *service = (UA_Service)Service_FindServersOnNetwork;
24348 *requestType = &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST];
24349 *responseType = &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE];
24350 *requiresSession = false;
24351 break;
24352# endif
24353 case UA_NS0ID_REGISTERSERVERREQUEST_ENCODING_DEFAULTBINARY:
24354 *service = (UA_Service)Service_RegisterServer;
24355 *requestType = &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST];
24356 *responseType = &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE];
24357 *requiresSession = false;
24358 break;
24359 case UA_NS0ID_REGISTERSERVER2REQUEST_ENCODING_DEFAULTBINARY:
24360 *service = (UA_Service)Service_RegisterServer2;
24361 *requestType = &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST];
24362 *responseType = &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE];
24363 *requiresSession = false;
24364 break;
24365#endif
24366 case UA_NS0ID_CREATESESSIONREQUEST_ENCODING_DEFAULTBINARY:
24367 *service = (UA_Service)Service_CreateSession;
24368 *requestType = &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST];
24369 *responseType = &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE];
24370 *requiresSession = false;
24371 break;
24372 case UA_NS0ID_ACTIVATESESSIONREQUEST_ENCODING_DEFAULTBINARY:
24373 *service = (UA_Service)Service_ActivateSession;
24374 *requestType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST];
24375 *responseType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE];
24376 break;
24377 case UA_NS0ID_CLOSESESSIONREQUEST_ENCODING_DEFAULTBINARY:
24378 *service = (UA_Service)Service_CloseSession;
24379 *requestType = &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST];
24380 *responseType = &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE];
24381 break;
24382 case UA_NS0ID_READREQUEST_ENCODING_DEFAULTBINARY:
24383 *service = NULL;
24384 *service = (UA_Service)Service_Read;
24385 *requestType = &UA_TYPES[UA_TYPES_READREQUEST];
24386 *responseType = &UA_TYPES[UA_TYPES_READRESPONSE];
24387 UA_SERVICECOUNTER_OFFSET(readCount);
24388 break;
24389 case UA_NS0ID_WRITEREQUEST_ENCODING_DEFAULTBINARY:
24390 *service = (UA_Service)Service_Write;
24391 *requestType = &UA_TYPES[UA_TYPES_WRITEREQUEST];
24392 *responseType = &UA_TYPES[UA_TYPES_WRITERESPONSE];
24393 UA_SERVICECOUNTER_OFFSET(writeCount);
24394 break;
24395 case UA_NS0ID_BROWSEREQUEST_ENCODING_DEFAULTBINARY:
24396 *service = (UA_Service)Service_Browse;
24397 *requestType = &UA_TYPES[UA_TYPES_BROWSEREQUEST];
24398 *responseType = &UA_TYPES[UA_TYPES_BROWSERESPONSE];
24399 UA_SERVICECOUNTER_OFFSET(browseCount);
24400 break;
24401 case UA_NS0ID_BROWSENEXTREQUEST_ENCODING_DEFAULTBINARY:
24402 *service = (UA_Service)Service_BrowseNext;
24403 *requestType = &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST];
24404 *responseType = &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE];
24405 UA_SERVICECOUNTER_OFFSET(browseNextCount);
24406 break;
24407 case UA_NS0ID_REGISTERNODESREQUEST_ENCODING_DEFAULTBINARY:
24408 *service = (UA_Service)Service_RegisterNodes;
24409 *requestType = &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST];
24410 *responseType = &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE];
24411 UA_SERVICECOUNTER_OFFSET(registerNodesCount);
24412 break;
24413 case UA_NS0ID_UNREGISTERNODESREQUEST_ENCODING_DEFAULTBINARY:
24414 *service = (UA_Service)Service_UnregisterNodes;
24415 *requestType = &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST];
24416 *responseType = &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE];
24417 UA_SERVICECOUNTER_OFFSET(unregisterNodesCount);
24418 break;
24419 case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_ENCODING_DEFAULTBINARY:
24420 *service = (UA_Service)Service_TranslateBrowsePathsToNodeIds;
24421 *requestType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST];
24422 *responseType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE];
24423 UA_SERVICECOUNTER_OFFSET(translateBrowsePathsToNodeIdsCount);
24424 break;
24425
24426#ifdef UA_ENABLE_SUBSCRIPTIONS
24427 case UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY:
24428 *service = (UA_Service)Service_CreateSubscription;
24429 *requestType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST];
24430 *responseType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE];
24431 UA_SERVICECOUNTER_OFFSET(createSubscriptionCount);
24432 break;
24433 case UA_NS0ID_PUBLISHREQUEST_ENCODING_DEFAULTBINARY:
24434 *requestType = &UA_TYPES[UA_TYPES_PUBLISHREQUEST];
24435 *responseType = &UA_TYPES[UA_TYPES_PUBLISHRESPONSE];
24436 UA_SERVICECOUNTER_OFFSET(publishCount);
24437 break;
24438 case UA_NS0ID_REPUBLISHREQUEST_ENCODING_DEFAULTBINARY:
24439 *service = (UA_Service)Service_Republish;
24440 *requestType = &UA_TYPES[UA_TYPES_REPUBLISHREQUEST];
24441 *responseType = &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE];
24442 UA_SERVICECOUNTER_OFFSET(republishCount);
24443 break;
24444 case UA_NS0ID_MODIFYSUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY:
24445 *service = (UA_Service)Service_ModifySubscription;
24446 *requestType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST];
24447 *responseType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE];
24448 UA_SERVICECOUNTER_OFFSET(modifySubscriptionCount);
24449 break;
24450 case UA_NS0ID_SETPUBLISHINGMODEREQUEST_ENCODING_DEFAULTBINARY:
24451 *service = (UA_Service)Service_SetPublishingMode;
24452 *requestType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST];
24453 *responseType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE];
24454 UA_SERVICECOUNTER_OFFSET(setPublishingModeCount);
24455 break;
24456 case UA_NS0ID_DELETESUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY:
24457 *service = (UA_Service)Service_DeleteSubscriptions;
24458 *requestType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST];
24459 *responseType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE];
24460 UA_SERVICECOUNTER_OFFSET(deleteSubscriptionsCount);
24461 break;
24462 case UA_NS0ID_TRANSFERSUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY:
24463 *service = (UA_Service)Service_TransferSubscriptions;
24464 *requestType = &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST];
24465 *responseType = &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE];
24466 UA_SERVICECOUNTER_OFFSET(transferSubscriptionsCount);
24467 break;
24468 case UA_NS0ID_CREATEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
24469 *service = (UA_Service)Service_CreateMonitoredItems;
24470 *requestType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST];
24471 *responseType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE];
24472 UA_SERVICECOUNTER_OFFSET(createMonitoredItemsCount);
24473 break;
24474 case UA_NS0ID_DELETEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
24475 *service = (UA_Service)Service_DeleteMonitoredItems;
24476 *requestType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST];
24477 *responseType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE];
24478 UA_SERVICECOUNTER_OFFSET(deleteMonitoredItemsCount);
24479 break;
24480 case UA_NS0ID_MODIFYMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
24481 *service = (UA_Service)Service_ModifyMonitoredItems;
24482 *requestType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST];
24483 *responseType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE];
24484 UA_SERVICECOUNTER_OFFSET(modifyMonitoredItemsCount);
24485 break;
24486 case UA_NS0ID_SETMONITORINGMODEREQUEST_ENCODING_DEFAULTBINARY:
24487 *service = (UA_Service)Service_SetMonitoringMode;
24488 *requestType = &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST];
24489 *responseType = &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE];
24490 UA_SERVICECOUNTER_OFFSET(setMonitoringModeCount);
24491 break;
24492 case UA_NS0ID_SETTRIGGERINGREQUEST_ENCODING_DEFAULTBINARY:
24493 *service = (UA_Service)Service_SetTriggering;
24494 *requestType = &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST];
24495 *responseType = &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE];
24496 UA_SERVICECOUNTER_OFFSET(setTriggeringCount);
24497 break;
24498#endif
24499#ifdef UA_ENABLE_HISTORIZING
24500 /* For History read */
24501 case UA_NS0ID_HISTORYREADREQUEST_ENCODING_DEFAULTBINARY:
24502 *service = (UA_Service)Service_HistoryRead;
24503 *requestType = &UA_TYPES[UA_TYPES_HISTORYREADREQUEST];
24504 *responseType = &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE];
24505 UA_SERVICECOUNTER_OFFSET(historyReadCount);
24506 break;
24507 /* For History update */
24508 case UA_NS0ID_HISTORYUPDATEREQUEST_ENCODING_DEFAULTBINARY:
24509 *service = (UA_Service)Service_HistoryUpdate;
24510 *requestType = &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST];
24511 *responseType = &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE];
24512 UA_SERVICECOUNTER_OFFSET(historyUpdateCount);
24513 break;
24514#endif
24515
24516#ifdef UA_ENABLE_METHODCALLS
24517 case UA_NS0ID_CALLREQUEST_ENCODING_DEFAULTBINARY:
24518 *service = (UA_Service)Service_Call;
24519 *requestType = &UA_TYPES[UA_TYPES_CALLREQUEST];
24520 *responseType = &UA_TYPES[UA_TYPES_CALLRESPONSE];
24521 UA_SERVICECOUNTER_OFFSET(callCount);
24522 break;
24523#endif
24524
24525#ifdef UA_ENABLE_NODEMANAGEMENT
24526 case UA_NS0ID_ADDNODESREQUEST_ENCODING_DEFAULTBINARY:
24527 *service = (UA_Service)Service_AddNodes;
24528 *requestType = &UA_TYPES[UA_TYPES_ADDNODESREQUEST];
24529 *responseType = &UA_TYPES[UA_TYPES_ADDNODESRESPONSE];
24530 UA_SERVICECOUNTER_OFFSET(addNodesCount);
24531 break;
24532 case UA_NS0ID_ADDREFERENCESREQUEST_ENCODING_DEFAULTBINARY:
24533 *service = (UA_Service)Service_AddReferences;
24534 *requestType = &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST];
24535 *responseType = &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE];
24536 UA_SERVICECOUNTER_OFFSET(addReferencesCount);
24537 break;
24538 case UA_NS0ID_DELETENODESREQUEST_ENCODING_DEFAULTBINARY:
24539 *service = (UA_Service)Service_DeleteNodes;
24540 *requestType = &UA_TYPES[UA_TYPES_DELETENODESREQUEST];
24541 *responseType = &UA_TYPES[UA_TYPES_DELETENODESRESPONSE];
24542 UA_SERVICECOUNTER_OFFSET(deleteNodesCount);
24543 break;
24544 case UA_NS0ID_DELETEREFERENCESREQUEST_ENCODING_DEFAULTBINARY:
24545 *service = (UA_Service)Service_DeleteReferences;
24546 *requestType = &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST];
24547 *responseType = &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE];
24548 UA_SERVICECOUNTER_OFFSET(deleteReferencesCount);
24549 break;
24550#endif
24551
24552 default:
24553 break;
24554 }
24555}
24556
24557/*************************/
24558/* Process Message Types */
24559/*************************/
24560
24561/* HEL -> Open up the connection */
24562static UA_StatusCode
24563processHEL(UA_Server *server, UA_SecureChannel *channel, const UA_ByteString *msg) {
24564 if(channel->state != UA_SECURECHANNELSTATE_FRESH)
24565 return UA_STATUSCODE_BADINTERNALERROR;
24566 size_t offset = 0; /* Go to the beginning of the TcpHelloMessage */
24567 UA_TcpHelloMessage helloMessage;
24568 UA_StatusCode retval =
24569 UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &helloMessage,
24570 type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE], NULL);
24571 if(retval != UA_STATUSCODE_GOOD)
24572 return retval;
24573
24574 /* Currently not checked */
24575 UA_String_clear(p: &helloMessage.endpointUrl);
24576
24577 /* Parameterize the connection. The TcpHelloMessage casts to a
24578 * TcpAcknowledgeMessage. */
24579 retval = UA_SecureChannel_processHELACK(channel,
24580 remoteConfig: (UA_TcpAcknowledgeMessage*)&helloMessage);
24581 if(retval != UA_STATUSCODE_GOOD) {
24582 UA_LOG_INFO(logger: &server->config.logger, category: UA_LOGCATEGORY_NETWORK,
24583 msg: "Connection %i | Error during the HEL/ACK handshake",
24584 (int)(channel->connection->sockfd));
24585 return retval;
24586 }
24587
24588 /* Get the send buffer from the network layer */
24589 UA_Connection *connection = channel->connection;
24590 UA_ByteString ack_msg;
24591 UA_ByteString_init(p: &ack_msg);
24592 retval = connection->getSendBuffer(connection, channel->config.sendBufferSize, &ack_msg);
24593 if(retval != UA_STATUSCODE_GOOD)
24594 return retval;
24595
24596 /* Build acknowledge response */
24597 UA_TcpAcknowledgeMessage ackMessage;
24598 ackMessage.protocolVersion = 0;
24599 ackMessage.receiveBufferSize = channel->config.recvBufferSize;
24600 ackMessage.sendBufferSize = channel->config.sendBufferSize;
24601 ackMessage.maxMessageSize = channel->config.localMaxMessageSize;
24602 ackMessage.maxChunkCount = channel->config.localMaxChunkCount;
24603
24604 UA_TcpMessageHeader ackHeader;
24605 ackHeader.messageTypeAndChunkType = UA_MESSAGETYPE_ACK + UA_CHUNKTYPE_FINAL;
24606 ackHeader.messageSize = 8 + 20; /* ackHeader + ackMessage */
24607
24608 /* Encode and send the response */
24609 UA_Byte *bufPos = ack_msg.data;
24610 const UA_Byte *bufEnd = &ack_msg.data[ack_msg.length];
24611 retval |= UA_encodeBinaryInternal(src: &ackHeader,
24612 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
24613 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
24614 retval |= UA_encodeBinaryInternal(src: &ackMessage,
24615 type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE],
24616 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
24617 if(retval != UA_STATUSCODE_GOOD) {
24618 connection->releaseSendBuffer(connection, &ack_msg);
24619 return retval;
24620 }
24621
24622 ack_msg.length = ackHeader.messageSize;
24623 retval = connection->send(connection, &ack_msg);
24624 if(retval == UA_STATUSCODE_GOOD)
24625 channel->state = UA_SECURECHANNELSTATE_ACK_SENT;
24626 return retval;
24627}
24628
24629/* OPN -> Open up/renew the securechannel */
24630static UA_StatusCode
24631processOPN(UA_Server *server, UA_SecureChannel *channel,
24632 const UA_UInt32 requestId, const UA_ByteString *msg) {
24633 if(channel->state != UA_SECURECHANNELSTATE_ACK_SENT &&
24634 channel->state != UA_SECURECHANNELSTATE_OPEN)
24635 return UA_STATUSCODE_BADINTERNALERROR;
24636 /* Decode the request */
24637 UA_NodeId requestType;
24638 UA_OpenSecureChannelRequest openSecureChannelRequest;
24639 size_t offset = 0;
24640 UA_StatusCode retval = UA_NodeId_decodeBinary(src: msg, offset: &offset, dst: &requestType);
24641 if(retval != UA_STATUSCODE_GOOD) {
24642 UA_NodeId_clear(p: &requestType);
24643 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24644 "Could not decode the NodeId. Closing the connection");
24645 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_REJECT);
24646 return retval;
24647 }
24648 retval = UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &openSecureChannelRequest,
24649 type: &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST], NULL);
24650
24651 /* Error occurred */
24652 if(retval != UA_STATUSCODE_GOOD ||
24653 !UA_NodeId_equal(n1: &requestType, n2: &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST].binaryEncodingId)) {
24654 UA_NodeId_clear(p: &requestType);
24655 UA_OpenSecureChannelRequest_clear(p: &openSecureChannelRequest);
24656 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24657 "Could not decode the OPN message. Closing the connection.");
24658 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_REJECT);
24659 return retval;
24660 }
24661 UA_NodeId_clear(p: &requestType);
24662
24663 /* Call the service */
24664 UA_OpenSecureChannelResponse openScResponse;
24665 UA_OpenSecureChannelResponse_init(p: &openScResponse);
24666 Service_OpenSecureChannel(server, channel, request: &openSecureChannelRequest, response: &openScResponse);
24667 UA_OpenSecureChannelRequest_clear(p: &openSecureChannelRequest);
24668 if(openScResponse.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
24669 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel, "Could not open a SecureChannel. "
24670 "Closing the connection.");
24671 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_REJECT);
24672 return openScResponse.responseHeader.serviceResult;
24673 }
24674
24675 /* Send the response */
24676 retval = UA_SecureChannel_sendAsymmetricOPNMessage(channel, requestId, content: &openScResponse,
24677 contentType: &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
24678 UA_OpenSecureChannelResponse_clear(p: &openScResponse);
24679 if(retval != UA_STATUSCODE_GOOD) {
24680 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24681 "Could not send the OPN answer with error code %s",
24682 UA_StatusCode_name(retval));
24683 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_REJECT);
24684 }
24685
24686 return retval;
24687}
24688
24689/* The responseHeader must have the requestHandle already set */
24690UA_StatusCode
24691sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
24692 UA_UInt32 requestId, UA_Response *response, const UA_DataType *responseType) {
24693 if(!channel)
24694 return UA_STATUSCODE_BADINTERNALERROR;
24695
24696 /* If the overall service call failed, answer with a ServiceFault */
24697 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
24698 return sendServiceFault(channel, requestId, requestHandle: response->responseHeader.requestHandle,
24699 statusCode: response->responseHeader.serviceResult);
24700
24701 /* Prepare the ResponseHeader */
24702 response->responseHeader.timestamp = UA_DateTime_now();
24703
24704 if(session) {
24705#ifdef UA_ENABLE_TYPEDESCRIPTION
24706 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
24707 "Sending response for RequestId %u of type %s",
24708 (unsigned)requestId, responseType->typeName);
24709#else
24710 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
24711 "Sending reponse for RequestId %u of type %" PRIu32,
24712 (unsigned)requestId, responseType->binaryEncodingId.identifier.numeric);
24713#endif
24714 } else {
24715#ifdef UA_ENABLE_TYPEDESCRIPTION
24716 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
24717 "Sending response for RequestId %u of type %s",
24718 (unsigned)requestId, responseType->typeName);
24719#else
24720 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
24721 "Sending reponse for RequestId %u of type %" PRIu32,
24722 (unsigned)requestId, responseType->binaryEncodingId.identifier.numeric);
24723#endif
24724 }
24725
24726 /* Start the message context */
24727 UA_MessageContext mc;
24728 UA_StatusCode retval = UA_MessageContext_begin(mc: &mc, channel, requestId, messageType: UA_MESSAGETYPE_MSG);
24729 if(retval != UA_STATUSCODE_GOOD)
24730 return retval;
24731
24732 /* Assert's required for clang-analyzer */
24733 UA_assert(mc.buf_pos == &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]);
24734 UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]);
24735
24736 /* Encode the response type */
24737 retval = UA_MessageContext_encode(mc: &mc, content: &responseType->binaryEncodingId,
24738 contentType: &UA_TYPES[UA_TYPES_NODEID]);
24739 if(retval != UA_STATUSCODE_GOOD)
24740 return retval;
24741
24742 /* Encode the response */
24743 retval = UA_MessageContext_encode(mc: &mc, content: response, contentType: responseType);
24744 if(retval != UA_STATUSCODE_GOOD)
24745 return retval;
24746
24747 /* Finish / send out */
24748 return UA_MessageContext_finish(mc: &mc);
24749}
24750
24751/* A Session is "bound" to a SecureChannel if it was created by the
24752 * SecureChannel or if it was activated on it. A Session can only be bound to
24753 * one SecureChannel. A Session can only be closed from the SecureChannel to
24754 * which it is bound.
24755 *
24756 * Returns Good if the AuthenticationToken exists nowhere (for CTT). */
24757UA_StatusCode
24758getBoundSession(UA_Server *server, const UA_SecureChannel *channel,
24759 const UA_NodeId *token, UA_Session **session) {
24760 UA_DateTime now = UA_DateTime_nowMonotonic();
24761 UA_SessionHeader *sh;
24762 SLIST_FOREACH(sh, &channel->sessions, next) {
24763 if(!UA_NodeId_equal(n1: token, n2: &sh->authenticationToken))
24764 continue;
24765 UA_Session *current = (UA_Session*)sh;
24766 /* Has the session timed out? */
24767 if(current->validTill < now) {
24768 server->serverDiagnosticsSummary.rejectedSessionCount++;
24769 return UA_STATUSCODE_BADSESSIONCLOSED;
24770 }
24771 *session = current;
24772 return UA_STATUSCODE_GOOD;
24773 }
24774
24775 server->serverDiagnosticsSummary.rejectedSessionCount++;
24776
24777 /* Session exists on another SecureChannel. The CTT expect this error. */
24778 UA_Session *tmpSession = getSessionByToken(server, token);
24779 if(tmpSession) {
24780#ifdef UA_ENABLE_DIAGNOSTICS
24781 tmpSession->diagnostics.unauthorizedRequestCount++;
24782#endif
24783 return UA_STATUSCODE_BADSECURECHANNELIDINVALID;
24784 }
24785
24786 return UA_STATUSCODE_GOOD;
24787}
24788
24789static const UA_String securityPolicyNone =
24790 UA_STRING_STATIC("http://opcfoundation.org/UA/SecurityPolicy#None");
24791
24792/* Returns a status of the SecureChannel. The detailed service status (usually
24793 * part of the response) is set in the serviceResult argument. */
24794static UA_StatusCode
24795processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 requestId,
24796 UA_Service service, const UA_Request *request,
24797 const UA_DataType *requestType, UA_Response *response,
24798 const UA_DataType *responseType, UA_Boolean sessionRequired,
24799 size_t counterOffset) {
24800 UA_Session *session = NULL;
24801 UA_StatusCode channelRes = UA_STATUSCODE_GOOD;
24802 UA_StatusCode serviceRes = UA_STATUSCODE_GOOD;
24803 const UA_RequestHeader *requestHeader = &request->requestHeader;
24804
24805 /* If it is an unencrypted (#None) channel, only allow the discovery services */
24806 if(server->config.securityPolicyNoneDiscoveryOnly &&
24807 UA_String_equal(s1: &channel->securityPolicy->policyUri, s2: &securityPolicyNone ) &&
24808 requestType != &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST] &&
24809 requestType != &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]
24810#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
24811 && requestType != &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST]
24812#endif
24813 ) {
24814 serviceRes = UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
24815 channelRes = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle,
24816 UA_STATUSCODE_BADSECURITYPOLICYREJECTED);
24817 goto update_statistics;
24818 }
24819
24820 /* Session lifecycle services. */
24821 if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST] ||
24822 requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST] ||
24823 requestType == &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]) {
24824 UA_LOCK(&server->serviceMutex);
24825 ((UA_ChannelService)service)(server, channel, request, response);
24826 UA_UNLOCK(&server->serviceMutex);
24827#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
24828 /* Store the authentication token so we can help fuzzing by setting
24829 * these values in the next request automatically */
24830 if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]) {
24831 UA_CreateSessionResponse *res = &response->createSessionResponse;
24832 UA_NodeId_copy(&res->authenticationToken, &unsafe_fuzz_authenticationToken);
24833 }
24834#endif
24835 serviceRes = response->responseHeader.serviceResult;
24836 channelRes = sendResponse(server, NULL, channel, requestId, response, responseType);
24837 goto update_statistics;
24838 }
24839
24840 /* Get the Session bound to the SecureChannel (not necessarily activated) */
24841 if(!UA_NodeId_isNull(p: &requestHeader->authenticationToken)) {
24842 UA_LOCK(&server->serviceMutex);
24843 UA_StatusCode retval =
24844 getBoundSession(server, channel,
24845 token: &requestHeader->authenticationToken, session: &session);
24846 UA_UNLOCK(&server->serviceMutex);
24847 if(retval != UA_STATUSCODE_GOOD) {
24848 serviceRes = response->responseHeader.serviceResult;
24849 channelRes = sendServiceFault(channel, requestId,
24850 requestHandle: requestHeader->requestHandle, statusCode: retval);
24851 goto update_statistics;
24852 }
24853 }
24854
24855 /* Set an anonymous, inactive session for services that need no session */
24856 UA_Session anonymousSession;
24857 if(!session) {
24858 if(sessionRequired) {
24859#ifdef UA_ENABLE_TYPEDESCRIPTION
24860 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24861 "%s refused without a valid session",
24862 requestType->typeName);
24863#else
24864 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24865 "Service %" PRIu32 " refused without a valid session",
24866 requestType->binaryEncodingId.identifier.numeric);
24867#endif
24868 serviceRes = UA_STATUSCODE_BADSESSIONIDINVALID;
24869 channelRes = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle,
24870 UA_STATUSCODE_BADSESSIONIDINVALID);
24871 goto update_statistics;
24872 }
24873
24874 UA_Session_init(session: &anonymousSession);
24875 anonymousSession.sessionId = UA_NODEID_GUID(nsIndex: 0, guid: UA_GUID_NULL);
24876 anonymousSession.header.channel = channel;
24877 session = &anonymousSession;
24878 }
24879
24880 UA_assert(session != NULL);
24881
24882 /* Trying to use a non-activated session? */
24883 if(sessionRequired && !session->activated) {
24884#ifdef UA_ENABLE_TYPEDESCRIPTION
24885 UA_LOG_WARNING_SESSION(&server->config.logger, session,
24886 "%s refused on a non-activated session",
24887 requestType->typeName);
24888#else
24889 UA_LOG_WARNING_SESSION(&server->config.logger, session,
24890 "Service %" PRIu32 " refused on a non-activated session",
24891 requestType->binaryEncodingId.identifier.numeric);
24892#endif
24893 if(session != &anonymousSession) {
24894 UA_LOCK(&server->serviceMutex);
24895 UA_Server_removeSessionByToken(server, token: &session->header.authenticationToken,
24896 event: UA_DIAGNOSTICEVENT_ABORT);
24897 UA_UNLOCK(&server->serviceMutex);
24898 }
24899 serviceRes = UA_STATUSCODE_BADSESSIONNOTACTIVATED;
24900 channelRes = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle,
24901 UA_STATUSCODE_BADSESSIONNOTACTIVATED);
24902 goto update_statistics;
24903 }
24904
24905 /* Update the session lifetime */
24906 UA_Session_updateLifetime(session);
24907
24908#ifdef UA_ENABLE_SUBSCRIPTIONS
24909 /* The publish request is not answered immediately */
24910 if(requestType == &UA_TYPES[UA_TYPES_PUBLISHREQUEST]) {
24911 UA_LOCK(&server->serviceMutex);
24912 serviceRes = Service_Publish(server, session, request: &request->publishRequest, requestId);
24913 /* No channelRes due to the async response */
24914 UA_UNLOCK(&server->serviceMutex);
24915 goto update_statistics;
24916 }
24917#endif
24918
24919#if UA_MULTITHREADING >= 100
24920 /* The call request might not be answered immediately */
24921 if(requestType == &UA_TYPES[UA_TYPES_CALLREQUEST]) {
24922 UA_Boolean finished = true;
24923 UA_LOCK(&server->serviceMutex);
24924 Service_CallAsync(server, session, requestId, &request->callRequest,
24925 &response->callResponse, &finished);
24926 UA_UNLOCK(&server->serviceMutex);
24927
24928 /* Async method calls remain. Don't send a response now. In case we have
24929 * an async call, count as a "good" request for the diagnostics
24930 * statistic. */
24931 if(UA_LIKELY(finished)) {
24932 serviceRes = response->responseHeader.serviceResult;
24933 channelRes = sendResponse(server, session, channel,
24934 requestId, response, responseType);
24935 }
24936 goto update_statistics;
24937 }
24938#endif
24939
24940 /* Execute the synchronous service call */
24941 UA_LOCK(&server->serviceMutex);
24942 service(server, session, request, response);
24943 UA_UNLOCK(&server->serviceMutex);
24944
24945 /* Send the response */
24946 serviceRes = response->responseHeader.serviceResult;
24947 channelRes = sendResponse(server, session, channel, requestId, response, responseType);
24948
24949 /* Update the diagnostics statistics */
24950 update_statistics:
24951#ifdef UA_ENABLE_DIAGNOSTICS
24952 if(session && session != &server->adminSession) {
24953 session->diagnostics.totalRequestCount.totalCount++;
24954 if(serviceRes != UA_STATUSCODE_GOOD)
24955 session->diagnostics.totalRequestCount.errorCount++;
24956 if(counterOffset != 0) {
24957 UA_ServiceCounterDataType *serviceCounter = (UA_ServiceCounterDataType*)
24958 (((uintptr_t)&session->diagnostics) + counterOffset);
24959 serviceCounter->totalCount++;
24960 if(serviceRes != UA_STATUSCODE_GOOD)
24961 serviceCounter->errorCount++;
24962 }
24963 }
24964#else
24965 (void)serviceRes; /* Pacify compiler warnings */
24966#endif
24967
24968 return channelRes;
24969}
24970
24971static UA_StatusCode
24972processMSG(UA_Server *server, UA_SecureChannel *channel,
24973 UA_UInt32 requestId, const UA_ByteString *msg) {
24974 if(channel->state != UA_SECURECHANNELSTATE_OPEN)
24975 return UA_STATUSCODE_BADINTERNALERROR;
24976 /* Decode the nodeid */
24977 size_t offset = 0;
24978 UA_NodeId requestTypeId;
24979 UA_StatusCode retval = UA_NodeId_decodeBinary(src: msg, offset: &offset, dst: &requestTypeId);
24980 if(retval != UA_STATUSCODE_GOOD)
24981 return retval;
24982 if(requestTypeId.namespaceIndex != 0 ||
24983 requestTypeId.identifierType != UA_NODEIDTYPE_NUMERIC)
24984 UA_NodeId_clear(p: &requestTypeId); /* leads to badserviceunsupported */
24985
24986 size_t requestPos = offset; /* Store the offset (for sendServiceFault) */
24987
24988 /* Get the service pointers */
24989 UA_Service service = NULL;
24990 UA_Boolean sessionRequired = true;
24991 const UA_DataType *requestType = NULL;
24992 const UA_DataType *responseType = NULL;
24993 size_t counterOffset = 0;
24994 getServicePointers(requestTypeId: requestTypeId.identifier.numeric, requestType: &requestType,
24995 responseType: &responseType, service: &service, requiresSession: &sessionRequired, counterOffset: &counterOffset);
24996 if(!requestType) {
24997 if(requestTypeId.identifier.numeric ==
24998 UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY) {
24999 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
25000 "Client requested a subscription, "
25001 "but those are not enabled in the build");
25002 } else {
25003 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
25004 "Unknown request with type identifier %" PRIi32,
25005 requestTypeId.identifier.numeric);
25006 }
25007 return decodeHeaderSendServiceFault(channel, msg, offset: requestPos,
25008 responseType: &UA_TYPES[UA_TYPES_SERVICEFAULT],
25009 requestId, UA_STATUSCODE_BADSERVICEUNSUPPORTED);
25010 }
25011 UA_assert(responseType);
25012
25013 /* Decode the request */
25014 UA_Request request;
25015 retval = UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &request,
25016 type: requestType, customTypes: server->config.customDataTypes);
25017 if(retval != UA_STATUSCODE_GOOD) {
25018 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
25019 "Could not decode the request with StatusCode %s",
25020 UA_StatusCode_name(retval));
25021 return decodeHeaderSendServiceFault(channel, msg, offset: requestPos,
25022 responseType, requestId, error: retval);
25023 }
25024
25025 /* Check timestamp in the request header */
25026 UA_RequestHeader *requestHeader = &request.requestHeader;
25027 if(requestHeader->timestamp == 0) {
25028 if(server->config.verifyRequestTimestamp <= UA_RULEHANDLING_WARN) {
25029 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
25030 "The server sends no timestamp in the request header. "
25031 "See the 'verifyRequestTimestamp' setting.");
25032 if(server->config.verifyRequestTimestamp <= UA_RULEHANDLING_ABORT) {
25033 retval = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle,
25034 UA_STATUSCODE_BADINVALIDTIMESTAMP);
25035 UA_clear(p: &request, type: requestType);
25036 return retval;
25037 }
25038 }
25039 }
25040
25041#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
25042 /* Set the authenticationToken from the create session request to help
25043 * fuzzing cover more lines */
25044 if(!UA_NodeId_isNull(&unsafe_fuzz_authenticationToken) &&
25045 !UA_NodeId_isNull(&requestHeader->authenticationToken)) {
25046 UA_NodeId_clear(&requestHeader->authenticationToken);
25047 UA_NodeId_copy(&unsafe_fuzz_authenticationToken, &requestHeader->authenticationToken);
25048 }
25049#endif
25050
25051 /* Prepare the respone and process the request */
25052 UA_Response response;
25053 UA_init(p: &response, type: responseType);
25054 response.responseHeader.requestHandle = requestHeader->requestHandle;
25055 retval = processMSGDecoded(server, channel, requestId, service, request: &request, requestType,
25056 response: &response, responseType, sessionRequired, counterOffset);
25057
25058 /* Clean up */
25059 UA_clear(p: &request, type: requestType);
25060 UA_clear(p: &response, type: responseType);
25061 return retval;
25062}
25063
25064/* Takes decoded messages starting at the nodeid of the content type. */
25065static UA_StatusCode
25066processSecureChannelMessage(void *application, UA_SecureChannel *channel,
25067 UA_MessageType messagetype, UA_UInt32 requestId,
25068 UA_ByteString *message) {
25069 UA_Server *server = (UA_Server*)application;
25070
25071 UA_StatusCode retval = UA_STATUSCODE_GOOD;
25072 switch(messagetype) {
25073 case UA_MESSAGETYPE_HEL:
25074 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process a HEL message");
25075 retval = processHEL(server, channel, msg: message);
25076 break;
25077 case UA_MESSAGETYPE_OPN:
25078 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process an OPN message");
25079 retval = processOPN(server, channel, requestId, msg: message);
25080 break;
25081 case UA_MESSAGETYPE_MSG:
25082 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process a MSG");
25083 retval = processMSG(server, channel, requestId, msg: message);
25084 break;
25085 case UA_MESSAGETYPE_CLO:
25086 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process a CLO");
25087 Service_CloseSecureChannel(server, channel); /* Regular close */
25088 break;
25089 default:
25090 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Invalid message type");
25091 retval = UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
25092 break;
25093 }
25094 if(retval != UA_STATUSCODE_GOOD) {
25095 if(!channel->connection) {
25096 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
25097 "Processing the message failed. Channel already closed "
25098 "with StatusCode %s. ", UA_StatusCode_name(retval));
25099 return retval;
25100 }
25101
25102 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
25103 "Processing the message failed with StatusCode %s. "
25104 "Closing the channel.", UA_StatusCode_name(retval));
25105 UA_TcpErrorMessage errMsg;
25106 UA_TcpErrorMessage_init(p: &errMsg);
25107 errMsg.error = retval;
25108 UA_Connection_sendError(connection: channel->connection, error: &errMsg);
25109 switch(retval) {
25110 case UA_STATUSCODE_BADSECURITYMODEREJECTED:
25111 case UA_STATUSCODE_BADSECURITYCHECKSFAILED:
25112 case UA_STATUSCODE_BADSECURECHANNELIDINVALID:
25113 case UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN:
25114 case UA_STATUSCODE_BADSECURITYPOLICYREJECTED:
25115 case UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED:
25116 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_SECURITYREJECT);
25117 break;
25118 default:
25119 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_CLOSE);
25120 break;
25121 }
25122 }
25123
25124 return retval;
25125}
25126
25127void
25128UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
25129 UA_ByteString *message) {
25130 UA_LOG_TRACE(logger: &server->config.logger, category: UA_LOGCATEGORY_NETWORK,
25131 msg: "Connection %i | Received a packet.", (int)(connection->sockfd));
25132
25133 UA_TcpErrorMessage error;
25134 UA_StatusCode retval = UA_STATUSCODE_GOOD;
25135 UA_SecureChannel *channel = connection->channel;
25136
25137 /* Add a SecureChannel to a new connection */
25138 if(!channel) {
25139 retval = UA_Server_createSecureChannel(server, connection);
25140 if(retval != UA_STATUSCODE_GOOD)
25141 goto error;
25142 channel = connection->channel;
25143 UA_assert(channel);
25144 }
25145
25146#ifdef UA_DEBUG_DUMP_PKGS
25147 UA_dump_hex_pkg(message->data, message->length);
25148#endif
25149#ifdef UA_DEBUG_DUMP_PKGS_FILE
25150 UA_debug_dumpCompleteChunk(server, channel->connection, message);
25151#endif
25152
25153 retval = UA_SecureChannel_processBuffer(channel, application: server, callback: processSecureChannelMessage, buffer: message);
25154 if(retval != UA_STATUSCODE_GOOD) {
25155 UA_LOG_INFO(logger: &server->config.logger, category: UA_LOGCATEGORY_NETWORK,
25156 msg: "Connection %i | Processing the message failed with error %s",
25157 (int)(connection->sockfd), UA_StatusCode_name(code: retval));
25158 goto error;
25159 }
25160
25161 return;
25162
25163 error:
25164 /* Send an ERR message and close the connection */
25165 error.error = retval;
25166 error.reason = UA_STRING_NULL;
25167 UA_Connection_sendError(connection, error: &error);
25168 connection->close(connection);
25169}
25170
25171void
25172UA_Server_removeConnection(UA_Server *server, UA_Connection *connection) {
25173 UA_Connection_detachSecureChannel(connection);
25174 connection->free(connection);
25175}
25176
25177/**** amalgamated original file "/src/server/ua_server_utils.c" ****/
25178
25179/* This Source Code Form is subject to the terms of the Mozilla Public
25180 * License, v. 2.0. If a copy of the MPL was not distributed with this
25181 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
25182 *
25183 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
25184 * Copyright 2016 (c) Lorenz Haas
25185 * Copyright 2017 (c) frax2222
25186 * Copyright 2017 (c) Florian Palm
25187 * Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
25188 * Copyright 2017 (c) Julian Grothoff
25189 */
25190
25191
25192const UA_DataType *
25193UA_Server_findDataType(UA_Server *server, const UA_NodeId *typeId) {
25194 return UA_findDataTypeWithCustom(typeId, customTypes: server->config.customDataTypes);
25195}
25196
25197/********************************/
25198/* Information Model Operations */
25199/********************************/
25200
25201const UA_Node *
25202getNodeType(UA_Server *server, const UA_NodeHead *head) {
25203 /* The reference to the parent is different for variable and variabletype */
25204 UA_Byte parentRefIndex;
25205 UA_Boolean inverse;
25206 UA_NodeClass typeNodeClass;
25207 switch(head->nodeClass) {
25208 case UA_NODECLASS_OBJECT:
25209 parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION;
25210 inverse = false;
25211 typeNodeClass = UA_NODECLASS_OBJECTTYPE;
25212 break;
25213 case UA_NODECLASS_VARIABLE:
25214 parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION;
25215 inverse = false;
25216 typeNodeClass = UA_NODECLASS_VARIABLETYPE;
25217 break;
25218 case UA_NODECLASS_OBJECTTYPE:
25219 case UA_NODECLASS_VARIABLETYPE:
25220 case UA_NODECLASS_REFERENCETYPE:
25221 case UA_NODECLASS_DATATYPE:
25222 parentRefIndex = UA_REFERENCETYPEINDEX_HASSUBTYPE;
25223 inverse = true;
25224 typeNodeClass = head->nodeClass;
25225 break;
25226 default:
25227 return NULL;
25228 }
25229
25230 /* Return the first matching candidate */
25231 for(size_t i = 0; i < head->referencesSize; ++i) {
25232 UA_NodeReferenceKind *rk = &head->references[i];
25233 if(rk->isInverse != inverse)
25234 continue;
25235 if(rk->referenceTypeIndex != parentRefIndex)
25236 continue;
25237
25238 const UA_ReferenceTarget *t = NULL;
25239 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
25240 const UA_Node *type = UA_NODESTORE_GETFROMREF(server, target: t->targetId);
25241 if(!type)
25242 continue;
25243 if(type->head.nodeClass == typeNodeClass)
25244 return type; /* Don't release the node that is returned */
25245 UA_NODESTORE_RELEASE(server, type);
25246 }
25247 }
25248
25249 return NULL;
25250}
25251
25252UA_Boolean
25253UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head) {
25254 for(size_t i = 0; i < head->referencesSize; ++i) {
25255 if(head->references[i].isInverse == false &&
25256 head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASSUBTYPE)
25257 return true;
25258 if(head->references[i].isInverse == true &&
25259 head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASTYPEDEFINITION)
25260 return true;
25261 }
25262 return false;
25263}
25264
25265UA_StatusCode
25266getParentTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *typeNode,
25267 UA_NodeId **typeHierarchy, size_t *typeHierarchySize) {
25268 UA_ReferenceTypeSet reftypes_subtype =
25269 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
25270 UA_ExpandedNodeId *subTypes = NULL;
25271 size_t subTypesSize = 0;
25272 UA_StatusCode retval = browseRecursive(server, startNodesSize: 1, startNodes: typeNode,
25273 browseDirection: UA_BROWSEDIRECTION_INVERSE,
25274 refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_UNSPECIFIED,
25275 false, resultsSize: &subTypesSize, results: &subTypes);
25276 if(retval != UA_STATUSCODE_GOOD)
25277 return retval;
25278
25279 UA_assert(subTypesSize < 1000);
25280
25281 UA_ReferenceTypeSet reftypes_interface =
25282 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
25283 UA_ExpandedNodeId *interfaces = NULL;
25284 size_t interfacesSize = 0;
25285 retval = browseRecursive(server, startNodesSize: 1, startNodes: typeNode, browseDirection: UA_BROWSEDIRECTION_FORWARD,
25286 refTypes: &reftypes_interface, nodeClassMask: UA_NODECLASS_UNSPECIFIED,
25287 false, resultsSize: &interfacesSize, results: &interfaces);
25288 if(retval != UA_STATUSCODE_GOOD) {
25289 UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_NODEID]);
25290 return retval;
25291 }
25292
25293 UA_assert(interfacesSize < 1000);
25294
25295 UA_NodeId *hierarchy = (UA_NodeId*)
25296 UA_malloc(size: sizeof(UA_NodeId) * (1 + subTypesSize + interfacesSize));
25297 if(!hierarchy) {
25298 UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25299 UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25300 return UA_STATUSCODE_BADOUTOFMEMORY;
25301 }
25302
25303 retval = UA_NodeId_copy(src: typeNode, dst: hierarchy);
25304 if(retval != UA_STATUSCODE_GOOD) {
25305 UA_free(ptr: hierarchy);
25306 UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25307 UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25308 return UA_STATUSCODE_BADOUTOFMEMORY;
25309 }
25310
25311 for(size_t i = 0; i < subTypesSize; i++) {
25312 hierarchy[i+1] = subTypes[i].nodeId;
25313 UA_NodeId_init(p: &subTypes[i].nodeId);
25314 }
25315 for(size_t i = 0; i < interfacesSize; i++) {
25316 hierarchy[i+1+subTypesSize] = interfaces[i].nodeId;
25317 UA_NodeId_init(p: &interfaces[i].nodeId);
25318 }
25319
25320 *typeHierarchy = hierarchy;
25321 *typeHierarchySize = subTypesSize + interfacesSize + 1;
25322
25323 UA_assert(*typeHierarchySize < 1000);
25324
25325 UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25326 UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25327 return UA_STATUSCODE_GOOD;
25328}
25329
25330UA_StatusCode
25331getAllInterfaceChildNodeIds(UA_Server *server, const UA_NodeId *objectNode,
25332 const UA_NodeId *objectTypeNode,
25333 UA_NodeId **interfaceChildNodes,
25334 size_t *interfaceChildNodesSize) {
25335 if(interfaceChildNodesSize == NULL || interfaceChildNodes == NULL)
25336 return UA_STATUSCODE_BADINTERNALERROR;
25337 *interfaceChildNodesSize = 0;
25338 *interfaceChildNodes = NULL;
25339
25340 UA_ExpandedNodeId *hasInterfaceCandidates = NULL;
25341 size_t hasInterfaceCandidatesSize = 0;
25342 UA_ReferenceTypeSet reftypes_subtype =
25343 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
25344
25345 UA_StatusCode retval =
25346 browseRecursive(server, startNodesSize: 1, startNodes: objectTypeNode, browseDirection: UA_BROWSEDIRECTION_INVERSE,
25347 refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_OBJECTTYPE,
25348 true, resultsSize: &hasInterfaceCandidatesSize,
25349 results: &hasInterfaceCandidates);
25350
25351 if(retval != UA_STATUSCODE_GOOD)
25352 return retval;
25353
25354 /* The interface could also have been added manually before calling UA_Server_addNode_finish
25355 * This can be handled by adding the object node as a start node for the HasInterface lookup */
25356 UA_ExpandedNodeId *resizedHasInterfaceCandidates = (UA_ExpandedNodeId*)
25357 UA_realloc(ptr: hasInterfaceCandidates,
25358 size: (hasInterfaceCandidatesSize + 1) * sizeof(UA_ExpandedNodeId));
25359
25360 if(!resizedHasInterfaceCandidates) {
25361 if(hasInterfaceCandidates)
25362 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize,
25363 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25364 return UA_STATUSCODE_BADOUTOFMEMORY;
25365 }
25366
25367 hasInterfaceCandidates = resizedHasInterfaceCandidates;
25368 hasInterfaceCandidatesSize += 1;
25369 UA_ExpandedNodeId_init(p: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1]);
25370
25371 UA_ExpandedNodeId_init(p: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1]);
25372 UA_NodeId_copy(src: objectNode, dst: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1].nodeId);
25373
25374 size_t outputIndex = 0;
25375
25376 for(size_t i = 0; i < hasInterfaceCandidatesSize; ++i) {
25377 UA_ReferenceTypeSet reftypes_interface =
25378 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
25379 UA_ExpandedNodeId *interfaceChildren = NULL;
25380 size_t interfacesChildrenSize = 0;
25381 retval = browseRecursive(server, startNodesSize: 1, startNodes: &hasInterfaceCandidates[i].nodeId,
25382 browseDirection: UA_BROWSEDIRECTION_FORWARD,
25383 refTypes: &reftypes_interface, nodeClassMask: UA_NODECLASS_OBJECTTYPE,
25384 false, resultsSize: &interfacesChildrenSize, results: &interfaceChildren);
25385 if(retval != UA_STATUSCODE_GOOD) {
25386 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize,
25387 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25388 if(*interfaceChildNodesSize) {
25389 UA_Array_delete(p: *interfaceChildNodes, size: *interfaceChildNodesSize,
25390 type: &UA_TYPES[UA_TYPES_NODEID]);
25391 *interfaceChildNodesSize = 0;
25392 }
25393 return retval;
25394 }
25395
25396 UA_assert(interfacesChildrenSize < 1000);
25397
25398 if(interfacesChildrenSize == 0) {
25399 continue;
25400 }
25401
25402 if(!*interfaceChildNodes) {
25403 *interfaceChildNodes = (UA_NodeId*)
25404 UA_calloc(nmemb: interfacesChildrenSize, size: sizeof(UA_NodeId));
25405 *interfaceChildNodesSize = interfacesChildrenSize;
25406
25407 if(!*interfaceChildNodes) {
25408 UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize,
25409 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25410 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize,
25411 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25412 return UA_STATUSCODE_BADOUTOFMEMORY;
25413 }
25414 } else {
25415 UA_NodeId *resizedInterfaceChildNodes = (UA_NodeId*)
25416 UA_realloc(ptr: *interfaceChildNodes,
25417 size: ((*interfaceChildNodesSize + interfacesChildrenSize) * sizeof(UA_NodeId)));
25418
25419 if(!resizedInterfaceChildNodes) {
25420 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize,
25421 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25422 UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize,
25423 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25424 return UA_STATUSCODE_BADOUTOFMEMORY;
25425 }
25426
25427 const size_t oldSize = *interfaceChildNodesSize;
25428 *interfaceChildNodesSize += interfacesChildrenSize;
25429 *interfaceChildNodes = resizedInterfaceChildNodes;
25430
25431 for(size_t j = oldSize; j < *interfaceChildNodesSize; ++j)
25432 UA_NodeId_init(p: &(*interfaceChildNodes)[j]);
25433 }
25434
25435 for(size_t j = 0; j < interfacesChildrenSize; j++) {
25436 (*interfaceChildNodes)[outputIndex++] = interfaceChildren[j].nodeId;
25437 }
25438
25439 UA_assert(*interfaceChildNodesSize < 1000);
25440 UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25441 }
25442
25443 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25444
25445 return UA_STATUSCODE_GOOD;
25446}
25447
25448/* For mulithreading: make a copy of the node, edit and replace.
25449 * For singlethreading: edit the original */
25450UA_StatusCode
25451UA_Server_editNode(UA_Server *server, UA_Session *session,
25452 const UA_NodeId *nodeId, UA_EditNodeCallback callback,
25453 void *data) {
25454#ifndef UA_ENABLE_IMMUTABLE_NODES
25455 /* Get the node and process it in-situ */
25456 const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
25457 if(!node)
25458 return UA_STATUSCODE_BADNODEIDUNKNOWN;
25459 UA_StatusCode retval = callback(server, session, (UA_Node*)(uintptr_t)node, data);
25460 UA_NODESTORE_RELEASE(server, node);
25461 return retval;
25462#else
25463 UA_StatusCode retval;
25464 do {
25465 /* Get an editable copy of the node */
25466 UA_Node *node;
25467 retval = UA_NODESTORE_GETCOPY(server, nodeId, &node);
25468 if(retval != UA_STATUSCODE_GOOD)
25469 return retval;
25470
25471 /* Run the operation on the copy */
25472 retval = callback(server, session, node, data);
25473 if(retval != UA_STATUSCODE_GOOD) {
25474 UA_NODESTORE_DELETE(server, node);
25475 return retval;
25476 }
25477
25478 /* Replace the node */
25479 retval = UA_NODESTORE_REPLACE(server, node);
25480 } while(retval != UA_STATUSCODE_GOOD);
25481 return retval;
25482#endif
25483}
25484
25485UA_StatusCode
25486UA_Server_processServiceOperations(UA_Server *server, UA_Session *session,
25487 UA_ServiceOperation operationCallback,
25488 const void *context, const size_t *requestOperations,
25489 const UA_DataType *requestOperationsType,
25490 size_t *responseOperations,
25491 const UA_DataType *responseOperationsType) {
25492 size_t ops = *requestOperations;
25493 if(ops == 0)
25494 return UA_STATUSCODE_BADNOTHINGTODO;
25495
25496 /* No padding after size_t */
25497 void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t));
25498 *respPos = UA_Array_new(size: ops, type: responseOperationsType);
25499 if(!(*respPos))
25500 return UA_STATUSCODE_BADOUTOFMEMORY;
25501
25502 *responseOperations = ops;
25503 uintptr_t respOp = (uintptr_t)*respPos;
25504 /* No padding after size_t */
25505 uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t));
25506 for(size_t i = 0; i < ops; i++) {
25507 operationCallback(server, session, context, (void*)reqOp, (void*)respOp);
25508 reqOp += requestOperationsType->memSize;
25509 respOp += responseOperationsType->memSize;
25510 }
25511 return UA_STATUSCODE_GOOD;
25512}
25513
25514/* A few global NodeId definitions */
25515const UA_NodeId subtypeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}};
25516const UA_NodeId hierarchicalReferences = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HIERARCHICALREFERENCES}};
25517
25518/*********************************/
25519/* Default attribute definitions */
25520/*********************************/
25521
25522const UA_ObjectAttributes UA_ObjectAttributes_default = {
25523 0, /* specifiedAttributes */
25524 {{0, NULL}, {0, NULL}}, /* displayName */
25525 {{0, NULL}, {0, NULL}}, /* description */
25526 0, 0, /* writeMask (userWriteMask) */
25527 0 /* eventNotifier */
25528};
25529
25530const UA_VariableAttributes UA_VariableAttributes_default = {
25531 0, /* specifiedAttributes */
25532 {{0, NULL}, {0, NULL}}, /* displayName */
25533 {{0, NULL}, {0, NULL}}, /* description */
25534 0, 0, /* writeMask (userWriteMask) */
25535 {NULL, UA_VARIANT_DATA,
25536 0, NULL, 0, NULL}, /* value */
25537 {0, UA_NODEIDTYPE_NUMERIC,
25538 {UA_NS0ID_BASEDATATYPE}}, /* dataType */
25539 UA_VALUERANK_ANY, /* valueRank */
25540 0, NULL, /* arrayDimensions */
25541 UA_ACCESSLEVELMASK_READ, 0, /* accessLevel (userAccessLevel) */
25542 0.0, /* minimumSamplingInterval */
25543 false /* historizing */
25544};
25545
25546const UA_MethodAttributes UA_MethodAttributes_default = {
25547 0, /* specifiedAttributes */
25548 {{0, NULL}, {0, NULL}}, /* displayName */
25549 {{0, NULL}, {0, NULL}}, /* description */
25550 0, 0, /* writeMask (userWriteMask) */
25551 true, true /* executable (userExecutable) */
25552};
25553
25554const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default = {
25555 0, /* specifiedAttributes */
25556 {{0, NULL}, {0, NULL}}, /* displayName */
25557 {{0, NULL}, {0, NULL}}, /* description */
25558 0, 0, /* writeMask (userWriteMask) */
25559 false /* isAbstract */
25560};
25561
25562const UA_VariableTypeAttributes UA_VariableTypeAttributes_default = {
25563 0, /* specifiedAttributes */
25564 {{0, NULL}, {0, NULL}}, /* displayName */
25565 {{0, NULL}, {0, NULL}}, /* description */
25566 0, 0, /* writeMask (userWriteMask) */
25567 {NULL, UA_VARIANT_DATA,
25568 0, NULL, 0, NULL}, /* value */
25569 {0, UA_NODEIDTYPE_NUMERIC,
25570 {UA_NS0ID_BASEDATATYPE}}, /* dataType */
25571 UA_VALUERANK_ANY, /* valueRank */
25572 0, NULL, /* arrayDimensions */
25573 false /* isAbstract */
25574};
25575
25576const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default = {
25577 0, /* specifiedAttributes */
25578 {{0, NULL}, {0, NULL}}, /* displayName */
25579 {{0, NULL}, {0, NULL}}, /* description */
25580 0, 0, /* writeMask (userWriteMask) */
25581 false, /* isAbstract */
25582 false, /* symmetric */
25583 {{0, NULL}, {0, NULL}} /* inverseName */
25584};
25585
25586const UA_DataTypeAttributes UA_DataTypeAttributes_default = {
25587 0, /* specifiedAttributes */
25588 {{0, NULL}, {0, NULL}}, /* displayName */
25589 {{0, NULL}, {0, NULL}}, /* description */
25590 0, 0, /* writeMask (userWriteMask) */
25591 false /* isAbstract */
25592};
25593
25594const UA_ViewAttributes UA_ViewAttributes_default = {
25595 0, /* specifiedAttributes */
25596 {{0, NULL}, {0, NULL}}, /* displayName */
25597 {{0, NULL}, {0, NULL}}, /* description */
25598 0, 0, /* writeMask (userWriteMask) */
25599 false, /* containsNoLoops */
25600 0 /* eventNotifier */
25601};
25602
25603
25604/**** amalgamated original file "/src/server/ua_server_discovery.c" ****/
25605
25606/* This Source Code Form is subject to the terms of the Mozilla Public
25607 * License, v. 2.0. If a copy of the MPL was not distributed with this
25608 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
25609 *
25610 * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
25611 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
25612 * Copyright 2017 (c) HMS Industrial Networks AB (Author: Jonas Green)
25613 */
25614
25615
25616
25617#ifdef UA_ENABLE_DISCOVERY
25618
25619UA_StatusCode
25620register_server_with_discovery_server(UA_Server *server,
25621 void *pClient,
25622 const UA_Boolean isUnregister,
25623 const char* semaphoreFilePath) {
25624 UA_Client *client = (UA_Client *) pClient;
25625
25626 /* Prepare the request. Do not cleanup the request after the service call,
25627 * as the members are stack-allocated or point into the server config. */
25628 UA_RegisterServer2Request request;
25629 UA_RegisterServer2Request_init(&request);
25630 request.requestHeader.timestamp = UA_DateTime_now();
25631 request.requestHeader.timeoutHint = 10000;
25632
25633 request.server.isOnline = !isUnregister;
25634 request.server.serverUri = server->config.applicationDescription.applicationUri;
25635 request.server.productUri = server->config.applicationDescription.productUri;
25636 request.server.serverType = server->config.applicationDescription.applicationType;
25637 request.server.gatewayServerUri = server->config.applicationDescription.gatewayServerUri;
25638
25639 if(semaphoreFilePath) {
25640#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
25641 request.server.semaphoreFilePath =
25642 UA_STRING((char*)(uintptr_t)semaphoreFilePath); /* dirty cast */
25643#else
25644 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_CLIENT,
25645 "Ignoring semaphore file path. open62541 not compiled "
25646 "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON");
25647#endif
25648 }
25649
25650 request.server.serverNames = &server->config.applicationDescription.applicationName;
25651 request.server.serverNamesSize = 1;
25652
25653 /* Mirror the discovery urls from the server config and the network layers */
25654 size_t config_discurls = server->config.applicationDescription.discoveryUrlsSize;
25655 size_t nl_discurls = server->config.networkLayersSize;
25656 size_t total_discurls = config_discurls + nl_discurls;
25657 request.server.discoveryUrls = (UA_String*)
25658 UA_Array_new(total_discurls, &UA_TYPES[UA_TYPES_STRING]);
25659 if(!request.server.discoveryUrls)
25660 return UA_STATUSCODE_BADOUTOFMEMORY;
25661
25662 for(size_t i = 0; i < config_discurls; ++i)
25663 request.server.discoveryUrls[i] = server->config.applicationDescription.discoveryUrls[i];
25664 /* TODO: Add nl only if discoveryUrl not already present */
25665 for(size_t i = 0; i < nl_discurls; ++i) {
25666 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
25667 request.server.discoveryUrls[config_discurls + i] = nl->discoveryUrl;
25668 }
25669 request.server.discoveryUrlsSize = total_discurls;
25670
25671#ifdef UA_ENABLE_DISCOVERY_MULTICAST
25672 request.discoveryConfigurationSize = 1;
25673 request.discoveryConfiguration = UA_ExtensionObject_new();
25674 // Set to NODELETE so that we can just use a pointer to the mdns config
25675 UA_ExtensionObject_setValueNoDelete(request.discoveryConfiguration,
25676 &server->config.mdnsConfig,
25677 &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]);
25678#endif
25679
25680 // First try with RegisterServer2, if that isn't implemented, use RegisterServer
25681 UA_RegisterServer2Response response;
25682 __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST],
25683 &response, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]);
25684
25685 UA_StatusCode serviceResult = response.responseHeader.serviceResult;
25686 UA_RegisterServer2Response_clear(&response);
25687 UA_Array_delete(request.discoveryConfiguration,
25688 request.discoveryConfigurationSize,
25689 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
25690 if(total_discurls > 0)
25691 UA_free(request.server.discoveryUrls);
25692
25693 if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED ||
25694 serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) {
25695 /* Try RegisterServer */
25696 UA_RegisterServerRequest request_fallback;
25697 UA_RegisterServerRequest_init(&request_fallback);
25698 /* Copy from RegisterServer2 request */
25699 request_fallback.requestHeader = request.requestHeader;
25700 request_fallback.server = request.server;
25701
25702 UA_RegisterServerResponse response_fallback;
25703
25704 __UA_Client_Service(client, &request_fallback,
25705 &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST],
25706 &response_fallback,
25707 &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]);
25708
25709 serviceResult = response_fallback.responseHeader.serviceResult;
25710 UA_RegisterServerResponse_clear(&response_fallback);
25711 }
25712
25713 if(serviceResult != UA_STATUSCODE_GOOD) {
25714 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_CLIENT,
25715 "RegisterServer/RegisterServer2 failed with statuscode %s",
25716 UA_StatusCode_name(serviceResult));
25717 }
25718
25719 return serviceResult;
25720}
25721
25722UA_StatusCode
25723UA_Server_register_discovery(UA_Server *server, UA_Client *client,
25724 const char* semaphoreFilePath) {
25725 UA_LOCK(&server->serviceMutex);
25726 UA_StatusCode retval = register_server_with_discovery_server(server, client,
25727 false, semaphoreFilePath);
25728 UA_UNLOCK(&server->serviceMutex);
25729 return retval;
25730}
25731
25732UA_StatusCode
25733UA_Server_unregister_discovery(UA_Server *server, UA_Client *client) {
25734 UA_LOCK(&server->serviceMutex);
25735 UA_StatusCode retval = register_server_with_discovery_server(server, client,
25736 true, NULL);
25737 UA_UNLOCK(&server->serviceMutex);
25738 return retval;
25739}
25740
25741#endif /* UA_ENABLE_DISCOVERY */
25742
25743/**** amalgamated original file "/src/server/ua_server_async.c" ****/
25744
25745/* This Source Code Form is subject to the terms of the Mozilla Public
25746 * License, v. 2.0. If a copy of the MPL was not distributed with this
25747 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
25748 *
25749 * Copyright 2019 (c) Fraunhofer IOSB (Author: Klaus Schick)
25750 * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
25751 */
25752
25753
25754#if UA_MULTITHREADING >= 100
25755
25756static void
25757UA_AsyncOperation_delete(UA_AsyncOperation *ar) {
25758 UA_CallMethodRequest_clear(&ar->request);
25759 UA_CallMethodResult_clear(&ar->response);
25760 UA_free(ar);
25761}
25762
25763static UA_StatusCode
25764UA_AsyncManager_sendAsyncResponse(UA_AsyncManager *am, UA_Server *server,
25765 UA_AsyncResponse *ar) {
25766 /* Get the session */
25767 UA_StatusCode res = UA_STATUSCODE_GOOD;
25768 UA_LOCK(&server->serviceMutex);
25769 UA_Session* session = UA_Server_getSessionById(server, &ar->sessionId);
25770 UA_UNLOCK(&server->serviceMutex);
25771 UA_SecureChannel* channel = NULL;
25772 UA_ResponseHeader *responseHeader = NULL;
25773 if(!session) {
25774 res = UA_STATUSCODE_BADSESSIONIDINVALID;
25775 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25776 "UA_Server_InsertMethodResponse: Session is gone");
25777 goto clean_up;
25778 }
25779
25780 /* Check the channel */
25781 channel = session->header.channel;
25782 if(!channel) {
25783 res = UA_STATUSCODE_BADSECURECHANNELCLOSED;
25784 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25785 "UA_Server_InsertMethodResponse: Channel is gone");
25786 goto clean_up;
25787 }
25788
25789 /* Okay, here we go, send the UA_CallResponse */
25790 responseHeader = (UA_ResponseHeader*)
25791 &ar->response.callResponse.responseHeader;
25792 responseHeader->requestHandle = ar->requestHandle;
25793 res = sendResponse(server, session, channel, ar->requestId,
25794 (UA_Response*)&ar->response, &UA_TYPES[UA_TYPES_CALLRESPONSE]);
25795 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
25796 "UA_Server_SendResponse: Response for Req# %" PRIu32 " sent", ar->requestId);
25797
25798 clean_up:
25799 /* Remove from the AsyncManager */
25800 UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar);
25801 return res;
25802}
25803
25804/* Integrate operation result in the AsyncResponse and send out the response if
25805 * it is ready. */
25806static void
25807integrateOperationResult(UA_AsyncManager *am, UA_Server *server,
25808 UA_AsyncOperation *ao) {
25809 /* Grab the open request, so we can continue to construct the response */
25810 UA_AsyncResponse *ar = ao->parent;
25811
25812 /* Reduce the number of open results */
25813 ar->opCountdown -= 1;
25814
25815 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
25816 "Return result in the server thread with %" PRIu32 " remaining",
25817 ar->opCountdown);
25818
25819 /* Move the UA_CallMethodResult to UA_CallResponse */
25820 ar->response.callResponse.results[ao->index] = ao->response;
25821 UA_CallMethodResult_init(&ao->response);
25822
25823 /* Are we done with all operations? */
25824 if(ar->opCountdown == 0)
25825 UA_AsyncManager_sendAsyncResponse(am, server, ar);
25826}
25827
25828/* Process all operations in the result queue -> move content over to the
25829 * AsyncResponse. This is only done by the server thread. */
25830static void
25831processAsyncResults(UA_Server *server, void *data) {
25832 UA_AsyncManager *am = &server->asyncManager;
25833 while(true) {
25834 UA_LOCK(&am->queueLock);
25835 UA_AsyncOperation *ao = TAILQ_FIRST(&am->resultQueue);
25836 if(ao)
25837 TAILQ_REMOVE(&am->resultQueue, ao, pointers);
25838 UA_UNLOCK(&am->queueLock);
25839 if(!ao)
25840 break;
25841 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
25842 "UA_Server_CallMethodResponse: Got Response: OKAY");
25843 integrateOperationResult(am, server, ao);
25844 UA_AsyncOperation_delete(ao);
25845 am->opsCount--;
25846 }
25847}
25848
25849/* Check if any operations have timed out */
25850static void
25851checkTimeouts(UA_Server *server, void *_) {
25852 /* Timeouts are not configured */
25853 if(server->config.asyncOperationTimeout <= 0.0)
25854 return;
25855
25856 UA_AsyncManager *am = &server->asyncManager;
25857 const UA_DateTime tNow = UA_DateTime_now();
25858
25859 UA_LOCK(&am->queueLock);
25860
25861 /* Loop over the queue of dispatched ops */
25862 UA_AsyncOperation *op = NULL, *op_tmp = NULL;
25863 TAILQ_FOREACH_SAFE(op, &am->dispatchedQueue, pointers, op_tmp) {
25864 /* The timeout has not passed. Also for all elements following in the queue. */
25865 if(tNow <= op->parent->timeout)
25866 break;
25867
25868 /* Mark as timed out and put it into the result queue */
25869 op->response.statusCode = UA_STATUSCODE_BADTIMEOUT;
25870 TAILQ_REMOVE(&am->dispatchedQueue, op, pointers);
25871 TAILQ_INSERT_TAIL(&am->resultQueue, op, pointers);
25872 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25873 "Operation was removed due to a timeout");
25874 }
25875
25876 /* Loop over the queue of new ops */
25877 TAILQ_FOREACH_SAFE(op, &am->newQueue, pointers, op_tmp) {
25878 /* The timeout has not passed. Also for all elements following in the queue. */
25879 if(tNow <= op->parent->timeout)
25880 break;
25881
25882 /* Mark as timed out and put it into the result queue */
25883 op->response.statusCode = UA_STATUSCODE_BADTIMEOUT;
25884 TAILQ_REMOVE(&am->newQueue, op, pointers);
25885 TAILQ_INSERT_TAIL(&am->resultQueue, op, pointers);
25886 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25887 "Operation was removed due to a timeout");
25888 }
25889
25890 UA_UNLOCK(&am->queueLock);
25891
25892 /* Integrate async results and send out complete responses */
25893 processAsyncResults(server, NULL);
25894}
25895
25896void
25897UA_AsyncManager_init(UA_AsyncManager *am, UA_Server *server) {
25898 memset(am, 0, sizeof(UA_AsyncManager));
25899 TAILQ_INIT(&am->asyncResponses);
25900 TAILQ_INIT(&am->newQueue);
25901 TAILQ_INIT(&am->dispatchedQueue);
25902 TAILQ_INIT(&am->resultQueue);
25903 UA_LOCK_INIT(&am->queueLock);
25904
25905 /* Add a regular callback for cleanup and sending finished responses at a
25906 * 100s interval. */
25907 UA_Server_addRepeatedCallback(server, (UA_ServerCallback)checkTimeouts,
25908 NULL, 100.0, &am->checkTimeoutCallbackId);
25909}
25910
25911void
25912UA_AsyncManager_clear(UA_AsyncManager *am, UA_Server *server) {
25913 removeCallback(server, am->checkTimeoutCallbackId);
25914
25915 UA_AsyncOperation *ar, *ar_tmp;
25916
25917 /* Clean up queues */
25918 UA_LOCK(&am->queueLock);
25919 TAILQ_FOREACH_SAFE(ar, &am->newQueue, pointers, ar_tmp) {
25920 TAILQ_REMOVE(&am->newQueue, ar, pointers);
25921 UA_AsyncOperation_delete(ar);
25922 }
25923 TAILQ_FOREACH_SAFE(ar, &am->dispatchedQueue, pointers, ar_tmp) {
25924 TAILQ_REMOVE(&am->dispatchedQueue, ar, pointers);
25925 UA_AsyncOperation_delete(ar);
25926 }
25927 TAILQ_FOREACH_SAFE(ar, &am->resultQueue, pointers, ar_tmp) {
25928 TAILQ_REMOVE(&am->resultQueue, ar, pointers);
25929 UA_AsyncOperation_delete(ar);
25930 }
25931 UA_UNLOCK(&am->queueLock);
25932
25933 /* Remove responses */
25934 UA_AsyncResponse *current, *temp;
25935 TAILQ_FOREACH_SAFE(current, &am->asyncResponses, pointers, temp) {
25936 UA_AsyncManager_removeAsyncResponse(am, current);
25937 }
25938
25939 /* Delete all locks */
25940 UA_LOCK_DESTROY(&am->queueLock);
25941}
25942
25943UA_StatusCode
25944UA_AsyncManager_createAsyncResponse(UA_AsyncManager *am, UA_Server *server,
25945 const UA_NodeId *sessionId,
25946 const UA_UInt32 requestId, const UA_UInt32 requestHandle,
25947 const UA_AsyncOperationType operationType,
25948 UA_AsyncResponse **outAr) {
25949 UA_AsyncResponse *newentry = (UA_AsyncResponse*)UA_calloc(1, sizeof(UA_AsyncResponse));
25950 if(!newentry)
25951 return UA_STATUSCODE_BADOUTOFMEMORY;
25952
25953 UA_StatusCode res = UA_NodeId_copy(sessionId, &newentry->sessionId);
25954 if(res != UA_STATUSCODE_GOOD) {
25955 UA_free(newentry);
25956 return res;
25957 }
25958
25959 am->asyncResponsesCount += 1;
25960 newentry->requestId = requestId;
25961 newentry->requestHandle = requestHandle;
25962 newentry->timeout = UA_DateTime_now();
25963 if(server->config.asyncOperationTimeout > 0.0)
25964 newentry->timeout += (UA_DateTime)
25965 (server->config.asyncOperationTimeout * (UA_DateTime)UA_DATETIME_MSEC);
25966 TAILQ_INSERT_TAIL(&am->asyncResponses, newentry, pointers);
25967
25968 *outAr = newentry;
25969 return UA_STATUSCODE_GOOD;
25970}
25971
25972/* Remove entry and free all allocated data */
25973void
25974UA_AsyncManager_removeAsyncResponse(UA_AsyncManager *am, UA_AsyncResponse *ar) {
25975 TAILQ_REMOVE(&am->asyncResponses, ar, pointers);
25976 am->asyncResponsesCount -= 1;
25977 UA_CallResponse_clear(&ar->response.callResponse);
25978 UA_NodeId_clear(&ar->sessionId);
25979 UA_free(ar);
25980}
25981
25982/* Enqueue next MethodRequest */
25983UA_StatusCode
25984UA_AsyncManager_createAsyncOp(UA_AsyncManager *am, UA_Server *server,
25985 UA_AsyncResponse *ar, size_t opIndex,
25986 const UA_CallMethodRequest *opRequest) {
25987 if(server->config.maxAsyncOperationQueueSize != 0 &&
25988 am->opsCount >= server->config.maxAsyncOperationQueueSize) {
25989 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25990 "UA_Server_SetNextAsyncMethod: Queue exceeds limit (%d).",
25991 (int unsigned)server->config.maxAsyncOperationQueueSize);
25992 return UA_STATUSCODE_BADUNEXPECTEDERROR;
25993 }
25994
25995 UA_AsyncOperation *ao = (UA_AsyncOperation*)UA_calloc(1, sizeof(UA_AsyncOperation));
25996 if(!ao) {
25997 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
25998 "UA_Server_SetNextAsyncMethod: Mem alloc failed.");
25999 return UA_STATUSCODE_BADOUTOFMEMORY;
26000 }
26001
26002 UA_StatusCode result = UA_CallMethodRequest_copy(opRequest, &ao->request);
26003 if(result != UA_STATUSCODE_GOOD) {
26004 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
26005 "UA_Server_SetAsyncMethodResult: UA_CallMethodRequest_copy failed.");
26006 UA_free(ao);
26007 return result;
26008 }
26009
26010 UA_CallMethodResult_init(&ao->response);
26011 ao->index = opIndex;
26012 ao->parent = ar;
26013
26014 UA_LOCK(&am->queueLock);
26015 TAILQ_INSERT_TAIL(&am->newQueue, ao, pointers);
26016 am->opsCount++;
26017 ar->opCountdown++;
26018 UA_UNLOCK(&am->queueLock);
26019
26020 if(server->config.asyncOperationNotifyCallback)
26021 server->config.asyncOperationNotifyCallback(server);
26022
26023 return UA_STATUSCODE_GOOD;
26024}
26025
26026/* Get and remove next Method Call Request */
26027UA_Boolean
26028UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType *type,
26029 const UA_AsyncOperationRequest **request,
26030 void **context, UA_DateTime *timeout) {
26031 UA_AsyncManager *am = &server->asyncManager;
26032
26033 UA_Boolean bRV = false;
26034 *type = UA_ASYNCOPERATIONTYPE_INVALID;
26035 UA_LOCK(&am->queueLock);
26036 UA_AsyncOperation *ao = TAILQ_FIRST(&am->newQueue);
26037 if(ao) {
26038 TAILQ_REMOVE(&am->newQueue, ao, pointers);
26039 TAILQ_INSERT_TAIL(&am->dispatchedQueue, ao, pointers);
26040 *type = UA_ASYNCOPERATIONTYPE_CALL;
26041 *request = (UA_AsyncOperationRequest*)&ao->request;
26042 *context = (void*)ao;
26043 if(timeout)
26044 *timeout = ao->parent->timeout;
26045 bRV = true;
26046 }
26047 UA_UNLOCK(&am->queueLock);
26048
26049 return bRV;
26050}
26051
26052/* Worker submits Method Call Response */
26053void
26054UA_Server_setAsyncOperationResult(UA_Server *server,
26055 const UA_AsyncOperationResponse *response,
26056 void *context) {
26057 UA_AsyncManager *am = &server->asyncManager;
26058
26059 UA_AsyncOperation *ao = (UA_AsyncOperation*)context;
26060 if(!ao) {
26061 /* Something went wrong. Not a good AsyncOp. */
26062 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
26063 "UA_Server_SetAsyncMethodResult: Invalid context");
26064 return;
26065 }
26066
26067 UA_LOCK(&am->queueLock);
26068
26069 /* See if the operation is still in the dispatched queue. Otherwise it has
26070 * been removed due to a timeout.
26071 *
26072 * TODO: Add a tree-structure for the dispatch queue. The linear lookup does
26073 * not scale. */
26074 UA_Boolean found = false;
26075 UA_AsyncOperation *op = NULL;
26076 TAILQ_FOREACH(op, &am->dispatchedQueue, pointers) {
26077 if(op == ao) {
26078 found = true;
26079 break;
26080 }
26081 }
26082
26083 if(!found) {
26084 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
26085 "UA_Server_SetAsyncMethodResult: The operation has timed out");
26086 UA_UNLOCK(&am->queueLock);
26087 return;
26088 }
26089
26090 /* Copy the result into the internal AsyncOperation */
26091 UA_StatusCode result =
26092 UA_CallMethodResult_copy(&response->callMethodResult, &ao->response);
26093 if(result != UA_STATUSCODE_GOOD) {
26094 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
26095 "UA_Server_SetAsyncMethodResult: UA_CallMethodResult_copy failed.");
26096 ao->response.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
26097 }
26098
26099 /* Move to the result queue */
26100 TAILQ_REMOVE(&am->dispatchedQueue, ao, pointers);
26101 TAILQ_INSERT_TAIL(&am->resultQueue, ao, pointers);
26102
26103 UA_UNLOCK(&am->queueLock);
26104
26105 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
26106 "Set the result from the worker thread");
26107}
26108
26109/******************/
26110/* Server Methods */
26111/******************/
26112
26113static UA_StatusCode
26114setMethodNodeAsync(UA_Server *server, UA_Session *session,
26115 UA_Node *node, UA_Boolean *isAsync) {
26116 if(node->head.nodeClass != UA_NODECLASS_METHOD)
26117 return UA_STATUSCODE_BADNODECLASSINVALID;
26118 node->methodNode.async = *isAsync;
26119 return UA_STATUSCODE_GOOD;
26120}
26121
26122UA_StatusCode
26123UA_Server_setMethodNodeAsync(UA_Server *server, const UA_NodeId id,
26124 UA_Boolean isAsync) {
26125 return UA_Server_editNode(server, &server->adminSession, &id,
26126 (UA_EditNodeCallback)setMethodNodeAsync, &isAsync);
26127}
26128
26129UA_StatusCode
26130UA_Server_processServiceOperationsAsync(UA_Server *server, UA_Session *session,
26131 UA_UInt32 requestId, UA_UInt32 requestHandle,
26132 UA_AsyncServiceOperation operationCallback,
26133 const size_t *requestOperations,
26134 const UA_DataType *requestOperationsType,
26135 size_t *responseOperations,
26136 const UA_DataType *responseOperationsType,
26137 UA_AsyncResponse **ar) {
26138 size_t ops = *requestOperations;
26139 if(ops == 0)
26140 return UA_STATUSCODE_BADNOTHINGTODO;
26141
26142 /* Allocate the response array. No padding after size_t */
26143 void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t));
26144 *respPos = UA_Array_new(ops, responseOperationsType);
26145 if(!*respPos)
26146 return UA_STATUSCODE_BADOUTOFMEMORY;
26147 *responseOperations = ops;
26148
26149 /* Finish / dispatch the operations. This may allocate a new AsyncResponse internally */
26150 uintptr_t respOp = (uintptr_t)*respPos;
26151 uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t));
26152 for(size_t i = 0; i < ops; i++) {
26153 operationCallback(server, session, requestId, requestHandle,
26154 i, (void*)reqOp, (void*)respOp, ar);
26155 reqOp += requestOperationsType->memSize;
26156 respOp += responseOperationsType->memSize;
26157 }
26158
26159 return UA_STATUSCODE_GOOD;
26160}
26161
26162#endif
26163
26164/**** amalgamated original file "/src/pubsub/ua_pubsub_networkmessage.c" ****/
26165
26166/* This Source Code Form is subject to the terms of the Mozilla Public
26167 * License, v. 2.0. If a copy of the MPL was not distributed with this
26168 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
26169 *
26170 * Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Tino Bischoff)
26171 * Copyright (c) 2019 Fraunhofer IOSB (Author: Andreas Ebner)
26172 */
26173
26174
26175
26176#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
26177
26178const UA_Byte NM_VERSION_MASK = 15;
26179const UA_Byte NM_PUBLISHER_ID_ENABLED_MASK = 16;
26180const UA_Byte NM_GROUP_HEADER_ENABLED_MASK = 32;
26181const UA_Byte NM_PAYLOAD_HEADER_ENABLED_MASK = 64;
26182const UA_Byte NM_EXTENDEDFLAGS1_ENABLED_MASK = 128;
26183const UA_Byte NM_PUBLISHER_ID_MASK = 7;
26184const UA_Byte NM_DATASET_CLASSID_ENABLED_MASK = 8;
26185const UA_Byte NM_SECURITY_ENABLED_MASK = 16;
26186const UA_Byte NM_TIMESTAMP_ENABLED_MASK = 32;
26187const UA_Byte NM_PICOSECONDS_ENABLED_MASK = 64;
26188const UA_Byte NM_EXTENDEDFLAGS2_ENABLED_MASK = 128;
26189const UA_Byte NM_NETWORK_MSG_TYPE_MASK = 28;
26190const UA_Byte NM_CHUNK_MESSAGE_MASK = 1;
26191const UA_Byte NM_PROMOTEDFIELDS_ENABLED_MASK = 2;
26192const UA_Byte GROUP_HEADER_WRITER_GROUPID_ENABLED = 1;
26193const UA_Byte GROUP_HEADER_GROUP_VERSION_ENABLED = 2;
26194const UA_Byte GROUP_HEADER_NM_NUMBER_ENABLED = 4;
26195const UA_Byte GROUP_HEADER_SEQUENCE_NUMBER_ENABLED = 8;
26196const UA_Byte SECURITY_HEADER_NM_SIGNED = 1;
26197const UA_Byte SECURITY_HEADER_NM_ENCRYPTED = 2;
26198const UA_Byte SECURITY_HEADER_SEC_FOOTER_ENABLED = 4;
26199const UA_Byte SECURITY_HEADER_FORCE_KEY_RESET = 8;
26200const UA_Byte DS_MESSAGEHEADER_DS_MSG_VALID = 1;
26201const UA_Byte DS_MESSAGEHEADER_FIELD_ENCODING_MASK = 6;
26202const UA_Byte DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK = 8;
26203const UA_Byte DS_MESSAGEHEADER_STATUS_ENABLED_MASK = 16;
26204const UA_Byte DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK = 32;
26205const UA_Byte DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK = 64;
26206const UA_Byte DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK = 128;
26207const UA_Byte DS_MESSAGEHEADER_DS_MESSAGE_TYPE_MASK = 15;
26208const UA_Byte DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK = 16;
26209const UA_Byte DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK = 32;
26210const UA_Byte NM_SHIFT_LEN = 2;
26211const UA_Byte DS_MH_SHIFT_LEN = 1;
26212
26213static UA_Boolean UA_NetworkMessage_ExtendedFlags1Enabled(const UA_NetworkMessage* src);
26214static UA_Boolean UA_NetworkMessage_ExtendedFlags2Enabled(const UA_NetworkMessage* src);
26215static UA_Boolean UA_DataSetMessageHeader_DataSetFlags2Enabled(const UA_DataSetMessageHeader* src);
26216
26217UA_StatusCode
26218UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer){
26219 UA_StatusCode rv = UA_STATUSCODE_GOOD;
26220 for(size_t i = 0; i < buffer->offsetsSize; ++i) {
26221 UA_NetworkMessageOffset *nmo = &buffer->offsets[i];
26222 const UA_Byte *bufEnd = &buffer->buffer.data[buffer->buffer.length];
26223 UA_Byte *bufPos = &buffer->buffer.data[nmo->offset];
26224 switch(nmo->contentType) {
26225 case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER:
26226 case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER:
26227 rv = UA_UInt16_encodeBinary((UA_UInt16 *)nmo->offsetData.value.value->value.data, &bufPos, bufEnd);
26228 if(*((UA_UInt16 *)nmo->offsetData.value.value->value.data) < UA_UINT16_MAX){
26229 (*((UA_UInt16 *)nmo->offsetData.value.value->value.data))++;
26230 } else {
26231 (*((UA_UInt16 *)nmo->offsetData.value.value->value.data)) = 0;
26232 }
26233 break;
26234 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE:
26235 rv = UA_DataValue_encodeBinary(nmo->offsetData.value.value,
26236 &bufPos, bufEnd);
26237 break;
26238 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT:
26239 rv = UA_Variant_encodeBinary(&nmo->offsetData.value.value->value,
26240 &bufPos, bufEnd);
26241 break;
26242 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW:
26243 rv = UA_encodeBinaryInternal(nmo->offsetData.value.value->value.data,
26244 nmo->offsetData.value.value->value.type,
26245 &bufPos, &bufEnd, NULL, NULL);
26246 break;
26247 case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING:
26248 break;
26249 default:
26250 return UA_STATUSCODE_BADNOTSUPPORTED;
26251 }
26252 }
26253 return rv;
26254}
26255
26256UA_StatusCode
26257UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
26258 const UA_ByteString *src, size_t *bufferPosition){
26259 UA_StatusCode rv = UA_STATUSCODE_GOOD;
26260 size_t payloadCounter = 0;
26261 size_t offset = 0;
26262 UA_DataSetMessage* dsm = buffer->nm->payload.dataSetPayload.dataSetMessages; //Considering one DSM in RT TODO: Clarify multiple DSM
26263 UA_DataSetMessageHeader header;
26264 size_t smallestRawOffset = UA_UINT32_MAX;
26265
26266 for (size_t i = 0; i < buffer->offsetsSize; ++i) {
26267 offset = buffer->offsets[i].offset + *bufferPosition;
26268 switch (buffer->offsets[i].contentType) {
26269 case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING:
26270 rv = UA_DataSetMessageHeader_decodeBinary(src, &offset, &header);
26271 if(rv != UA_STATUSCODE_GOOD)
26272 return rv;
26273 break;
26274 case UA_PUBSUB_OFFSETTYPE_PUBLISHERID:
26275 switch (buffer->nm->publisherIdType) {
26276 case UA_PUBLISHERDATATYPE_BYTE:
26277 rv = UA_Byte_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdByte));
26278 break;
26279 case UA_PUBLISHERDATATYPE_UINT16:
26280 rv = UA_UInt16_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt16));
26281 break;
26282 case UA_PUBLISHERDATATYPE_UINT32:
26283 rv = UA_UInt32_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt32));
26284 break;
26285 case UA_PUBLISHERDATATYPE_UINT64:
26286 rv = UA_UInt64_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt64));
26287 break;
26288 default:
26289 return UA_STATUSCODE_BADNOTSUPPORTED;
26290 }
26291 break;
26292 case UA_PUBSUB_OFFSETTYPE_WRITERGROUPID:
26293 rv = UA_UInt16_decodeBinary(src, &offset, &buffer->nm->groupHeader.writerGroupId);
26294 UA_CHECK_STATUS(rv, return rv);
26295 break;
26296 case UA_PUBSUB_OFFSETTYPE_DATASETWRITERID:
26297 rv = UA_UInt16_decodeBinary(src, &offset,
26298 &buffer->nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]); /* TODO */
26299 UA_CHECK_STATUS(rv, return rv);
26300 break;
26301 case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER:
26302 rv = UA_UInt16_decodeBinary(src, &offset, &buffer->nm->groupHeader.sequenceNumber);
26303 UA_CHECK_STATUS(rv, return rv);
26304 break;
26305 case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER:
26306 rv = UA_UInt16_decodeBinary(src, &offset, &(dsm->header.dataSetMessageSequenceNr));
26307 UA_CHECK_STATUS(rv, return rv);
26308 break;
26309 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE:
26310 rv = UA_DataValue_decodeBinary(src, &offset,
26311 &(dsm->data.keyFrameData.dataSetFields[payloadCounter]));
26312 UA_CHECK_STATUS(rv, return rv);
26313 payloadCounter++;
26314 break;
26315 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT:
26316 rv = UA_Variant_decodeBinary(src, &offset,
26317 &dsm->data.keyFrameData.dataSetFields[payloadCounter].value);
26318 UA_CHECK_STATUS(rv, return rv);
26319 dsm->data.keyFrameData.dataSetFields[payloadCounter].hasValue = true;
26320 payloadCounter++;
26321 break;
26322 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW:
26323 /* We need only the start address of the raw fields */
26324 if (smallestRawOffset > offset){
26325 smallestRawOffset = offset;
26326 dsm->data.keyFrameData.rawFields.data = &src->data[offset];
26327 dsm->data.keyFrameData.rawFields.length = buffer->rawMessageLength;
26328 }
26329 payloadCounter++;
26330 break;
26331 default:
26332 return UA_STATUSCODE_BADNOTSUPPORTED;
26333 }
26334 }
26335 //check if the frame is of type "raw" payload
26336 if(smallestRawOffset != UA_UINT32_MAX){
26337 *bufferPosition = smallestRawOffset + buffer->rawMessageLength;
26338 } else {
26339 *bufferPosition = offset;
26340 }
26341
26342 return rv;
26343}
26344
26345static
26346UA_StatusCode
26347UA_NetworkMessageHeader_encodeBinary(const UA_NetworkMessage *src, UA_Byte **bufPos,
26348 const UA_Byte *bufEnd) {
26349
26350 /* UADPVersion + UADP Flags */
26351 UA_Byte v = src->version;
26352 if(src->publisherIdEnabled)
26353 v |= NM_PUBLISHER_ID_ENABLED_MASK;
26354
26355 if(src->groupHeaderEnabled)
26356 v |= NM_GROUP_HEADER_ENABLED_MASK;
26357
26358 if(src->payloadHeaderEnabled)
26359 v |= NM_PAYLOAD_HEADER_ENABLED_MASK;
26360
26361 if(UA_NetworkMessage_ExtendedFlags1Enabled(src))
26362 v |= NM_EXTENDEDFLAGS1_ENABLED_MASK;
26363
26364 UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26365 UA_CHECK_STATUS(rv, return rv);
26366 // ExtendedFlags1
26367 if(UA_NetworkMessage_ExtendedFlags1Enabled(src)) {
26368 v = (UA_Byte)src->publisherIdType;
26369
26370 if(src->dataSetClassIdEnabled)
26371 v |= NM_DATASET_CLASSID_ENABLED_MASK;
26372
26373 if(src->securityEnabled)
26374 v |= NM_SECURITY_ENABLED_MASK;
26375
26376 if(src->timestampEnabled)
26377 v |= NM_TIMESTAMP_ENABLED_MASK;
26378
26379 if(src->picosecondsEnabled)
26380 v |= NM_PICOSECONDS_ENABLED_MASK;
26381
26382 if(UA_NetworkMessage_ExtendedFlags2Enabled(src))
26383 v |= NM_EXTENDEDFLAGS2_ENABLED_MASK;
26384
26385 rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26386 UA_CHECK_STATUS(rv, return rv);
26387
26388 // ExtendedFlags2
26389 if(UA_NetworkMessage_ExtendedFlags2Enabled(src)) {
26390 v = (UA_Byte)src->networkMessageType;
26391 // shift left 2 bit
26392 v = (UA_Byte) (v << NM_SHIFT_LEN);
26393
26394 if(src->chunkMessage)
26395 v |= NM_CHUNK_MESSAGE_MASK;
26396
26397 if(src->promotedFieldsEnabled)
26398 v |= NM_PROMOTEDFIELDS_ENABLED_MASK;
26399
26400 rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26401 UA_CHECK_STATUS(rv, return rv);
26402 }
26403 }
26404
26405 // PublisherId
26406 if(src->publisherIdEnabled) {
26407 switch (src->publisherIdType) {
26408 case UA_PUBLISHERDATATYPE_BYTE:
26409 rv = UA_Byte_encodeBinary(&(src->publisherId.publisherIdByte), bufPos, bufEnd);
26410 break;
26411
26412 case UA_PUBLISHERDATATYPE_UINT16:
26413 rv = UA_UInt16_encodeBinary(&(src->publisherId.publisherIdUInt16), bufPos, bufEnd);
26414 break;
26415
26416 case UA_PUBLISHERDATATYPE_UINT32:
26417 rv = UA_UInt32_encodeBinary(&(src->publisherId.publisherIdUInt32), bufPos, bufEnd);
26418 break;
26419
26420 case UA_PUBLISHERDATATYPE_UINT64:
26421 rv = UA_UInt64_encodeBinary(&(src->publisherId.publisherIdUInt64), bufPos, bufEnd);
26422 break;
26423
26424 case UA_PUBLISHERDATATYPE_STRING:
26425 rv = UA_String_encodeBinary(&(src->publisherId.publisherIdString), bufPos, bufEnd);
26426 break;
26427
26428 default:
26429 rv = UA_STATUSCODE_BADINTERNALERROR;
26430 break;
26431 }
26432 UA_CHECK_STATUS(rv, return rv);
26433 }
26434
26435 // DataSetClassId
26436 if(src->dataSetClassIdEnabled) {
26437 rv = UA_Guid_encodeBinary(&(src->dataSetClassId), bufPos, bufEnd);
26438 UA_CHECK_STATUS(rv, return rv);
26439 }
26440 return UA_STATUSCODE_GOOD;
26441}
26442
26443static
26444UA_StatusCode
26445UA_GroupHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26446 const UA_Byte *bufEnd) {
26447
26448 UA_Byte v = 0;
26449
26450 if(src->groupHeader.writerGroupIdEnabled)
26451 v |= GROUP_HEADER_WRITER_GROUPID_ENABLED;
26452
26453 if(src->groupHeader.groupVersionEnabled)
26454 v |= GROUP_HEADER_GROUP_VERSION_ENABLED;
26455
26456 if(src->groupHeader.networkMessageNumberEnabled)
26457 v |= GROUP_HEADER_NM_NUMBER_ENABLED;
26458
26459 if(src->groupHeader.sequenceNumberEnabled)
26460 v |= GROUP_HEADER_SEQUENCE_NUMBER_ENABLED;
26461
26462 UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26463 UA_CHECK_STATUS(rv, return rv);
26464
26465 if(src->groupHeader.writerGroupIdEnabled) {
26466 rv = UA_UInt16_encodeBinary(&(src->groupHeader.writerGroupId), bufPos, bufEnd);
26467 UA_CHECK_STATUS(rv, return rv);
26468 }
26469
26470 if(src->groupHeader.groupVersionEnabled) {
26471 rv = UA_UInt32_encodeBinary(&(src->groupHeader.groupVersion), bufPos, bufEnd);
26472 UA_CHECK_STATUS(rv, return rv);
26473 }
26474
26475 if(src->groupHeader.networkMessageNumberEnabled) {
26476 rv = UA_UInt16_encodeBinary(&(src->groupHeader.networkMessageNumber), bufPos, bufEnd);
26477 UA_CHECK_STATUS(rv, return rv);
26478 }
26479
26480 if(src->groupHeader.sequenceNumberEnabled) {
26481 rv = UA_UInt16_encodeBinary(&(src->groupHeader.sequenceNumber), bufPos, bufEnd);
26482 UA_CHECK_STATUS(rv, return rv);
26483 }
26484 return UA_STATUSCODE_GOOD;
26485}
26486
26487static
26488UA_StatusCode
26489UA_PayloadHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26490 const UA_Byte *bufEnd) {
26491
26492 if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
26493 return UA_STATUSCODE_BADNOTIMPLEMENTED;
26494
26495 UA_StatusCode rv = UA_Byte_encodeBinary(&(src->payloadHeader.dataSetPayloadHeader.count), bufPos, bufEnd);
26496 UA_CHECK_STATUS(rv, return rv);
26497
26498 if(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds == NULL)
26499 return UA_STATUSCODE_BADENCODINGERROR;
26500
26501 for(UA_Byte i = 0; i < src->payloadHeader.dataSetPayloadHeader.count; i++) {
26502 rv = UA_UInt16_encodeBinary(&(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]),
26503 bufPos, bufEnd);
26504 UA_CHECK_STATUS(rv, return rv);
26505 }
26506 return UA_STATUSCODE_GOOD;
26507}
26508
26509static
26510UA_StatusCode
26511UA_ExtendedNetworkMessageHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26512 const UA_Byte *bufEnd) {
26513
26514 UA_StatusCode rv = UA_STATUSCODE_GOOD;
26515 // Timestamp
26516 if(src->timestampEnabled)
26517 rv = UA_DateTime_encodeBinary(&(src->timestamp), bufPos, bufEnd);
26518
26519 UA_CHECK_STATUS(rv, return rv);
26520 // Picoseconds
26521 if(src->picosecondsEnabled)
26522 rv = UA_UInt16_encodeBinary(&(src->picoseconds), bufPos, bufEnd);
26523
26524 UA_CHECK_STATUS(rv, return rv);
26525 // PromotedFields
26526 if(src->promotedFieldsEnabled) {
26527 /* Size (calculate & encode) */
26528 UA_UInt16 pfSize = 0;
26529 for(UA_UInt16 i = 0; i < src->promotedFieldsSize; i++)
26530 pfSize = (UA_UInt16) (pfSize + UA_Variant_calcSizeBinary(&src->promotedFields[i]));
26531 rv |= UA_UInt16_encodeBinary(&pfSize, bufPos, bufEnd);
26532 UA_CHECK_STATUS(rv, return rv);
26533
26534 for (UA_UInt16 i = 0; i < src->promotedFieldsSize; i++)
26535 rv |= UA_Variant_encodeBinary(&(src->promotedFields[i]), bufPos, bufEnd);
26536 UA_CHECK_STATUS(rv, return rv);
26537 }
26538 return UA_STATUSCODE_GOOD;
26539}
26540
26541static
26542UA_StatusCode
26543UA_SecurityHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26544 const UA_Byte *bufEnd) {
26545 // SecurityFlags
26546 UA_Byte v = 0;
26547 if(src->securityHeader.networkMessageSigned)
26548 v |= SECURITY_HEADER_NM_SIGNED;
26549
26550 if(src->securityHeader.networkMessageEncrypted)
26551 v |= SECURITY_HEADER_NM_ENCRYPTED;
26552
26553 if(src->securityHeader.securityFooterEnabled)
26554 v |= SECURITY_HEADER_SEC_FOOTER_ENABLED;
26555
26556 if(src->securityHeader.forceKeyReset)
26557 v |= SECURITY_HEADER_FORCE_KEY_RESET;
26558
26559 UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26560 UA_CHECK_STATUS(rv, return rv);
26561 // SecurityTokenId
26562 rv = UA_UInt32_encodeBinary(&src->securityHeader.securityTokenId, bufPos, bufEnd);
26563 UA_CHECK_STATUS(rv, return rv);
26564 // NonceLength
26565 UA_Byte nonceLength = (UA_Byte)src->securityHeader.messageNonce.length;
26566 rv = UA_Byte_encodeBinary(&nonceLength, bufPos, bufEnd);
26567 UA_CHECK_STATUS(rv, return rv);
26568 // MessageNonce
26569 for (size_t i = 0; i < src->securityHeader.messageNonce.length; i++) {
26570 rv = UA_Byte_encodeBinary(&src->securityHeader.messageNonce.data[i],
26571 bufPos, bufEnd);
26572 UA_CHECK_STATUS(rv, return rv);
26573 }
26574
26575 // SecurityFooterSize
26576 if(src->securityHeader.securityFooterEnabled) {
26577 rv = UA_UInt16_encodeBinary(&src->securityHeader.securityFooterSize,
26578 bufPos, bufEnd);
26579 UA_CHECK_STATUS(rv, return rv);
26580 }
26581
26582 return UA_STATUSCODE_GOOD;
26583}
26584
26585UA_StatusCode
26586UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage* src, UA_Byte **bufPos,
26587 const UA_Byte *bufEnd) {
26588
26589 UA_StatusCode rv = UA_NetworkMessageHeader_encodeBinary(src, bufPos, bufEnd);
26590 UA_CHECK_STATUS(rv, return rv);
26591 // Group Header
26592 if(src->groupHeaderEnabled) {
26593 rv = UA_GroupHeader_encodeBinary(src, bufPos, bufEnd);
26594 UA_CHECK_STATUS(rv, return rv);
26595 }
26596
26597 // Payload Header
26598 if(src->payloadHeaderEnabled) {
26599 rv = UA_PayloadHeader_encodeBinary(src, bufPos, bufEnd);
26600 UA_CHECK_STATUS(rv, return rv);
26601 }
26602
26603 // Extended Network Message Header
26604 rv = UA_ExtendedNetworkMessageHeader_encodeBinary(src, bufPos, bufEnd);
26605 UA_CHECK_STATUS(rv, return rv);
26606 // SecurityHeader
26607 if(src->securityEnabled) {
26608 rv = UA_SecurityHeader_encodeBinary(src, bufPos, bufEnd);
26609 UA_CHECK_STATUS(rv, return rv);
26610 }
26611 return UA_STATUSCODE_GOOD;
26612}
26613
26614
26615UA_StatusCode
26616UA_NetworkMessage_encodePayload(const UA_NetworkMessage* src, UA_Byte **bufPos,
26617 const UA_Byte *bufEnd) {
26618
26619 UA_StatusCode rv;
26620
26621 // Payload
26622 if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
26623 return UA_STATUSCODE_BADNOTIMPLEMENTED;
26624
26625 UA_Byte count = 1;
26626
26627 if(src->payloadHeaderEnabled) {
26628 count = src->payloadHeader.dataSetPayloadHeader.count;
26629 if(count > 1) {
26630 for (UA_Byte i = 0; i < count; i++) {
26631 // initially calculate the size, if not specified
26632 UA_UInt16 sz = 0;
26633 if((src->payload.dataSetPayload.sizes != NULL) &&
26634 (src->payload.dataSetPayload.sizes[i] != 0)) {
26635 sz = src->payload.dataSetPayload.sizes[i];
26636 } else {
26637 sz = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&src->payload.dataSetPayload.dataSetMessages[i],
26638 NULL, 0);
26639 }
26640
26641 rv = UA_UInt16_encodeBinary(&sz, bufPos, bufEnd);
26642 UA_CHECK_STATUS(rv, return rv);
26643 }
26644 }
26645 }
26646
26647 for(UA_Byte i = 0; i < count; i++) {
26648 rv = UA_DataSetMessage_encodeBinary(&(src->payload.dataSetPayload.dataSetMessages[i]), bufPos, bufEnd);
26649 UA_CHECK_STATUS(rv, return rv);
26650 }
26651
26652 return UA_STATUSCODE_GOOD;
26653}
26654
26655UA_StatusCode
26656UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src, UA_Byte **bufPos,
26657 const UA_Byte *bufEnd) {
26658
26659 if(src->securityEnabled) {
26660 // SecurityFooter
26661 if(src->securityHeader.securityFooterEnabled) {
26662 for(size_t i = 0; i < src->securityHeader.securityFooterSize; i++) {
26663 UA_StatusCode rv = UA_Byte_encodeBinary(&(src->securityFooter.data[i]), bufPos, bufEnd);
26664 UA_CHECK_STATUS(rv, return rv);
26665 }
26666 }
26667 }
26668 return UA_STATUSCODE_GOOD;
26669}
26670
26671UA_StatusCode
26672UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26673 const UA_Byte *bufEnd, UA_Byte **dataToEncryptStart) {
26674
26675 UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(src, bufPos, bufEnd);
26676 UA_CHECK_STATUS(rv, return rv);
26677
26678 if(dataToEncryptStart) {
26679 *dataToEncryptStart = *bufPos;
26680 }
26681
26682 rv = UA_NetworkMessage_encodePayload(src, bufPos, bufEnd);
26683 UA_CHECK_STATUS(rv, return rv);
26684
26685 rv = UA_NetworkMessage_encodeFooters(src, bufPos, bufEnd);
26686 UA_CHECK_STATUS(rv, return rv);
26687
26688 return UA_STATUSCODE_GOOD;
26689}
26690
26691UA_StatusCode
26692UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
26693 UA_Byte decoded = 0;
26694 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
26695 UA_CHECK_STATUS(rv, return rv);
26696
26697 dst->version = decoded & NM_VERSION_MASK;
26698
26699 if((decoded & NM_PUBLISHER_ID_ENABLED_MASK) != 0)
26700 dst->publisherIdEnabled = true;
26701
26702 if((decoded & NM_GROUP_HEADER_ENABLED_MASK) != 0)
26703 dst->groupHeaderEnabled = true;
26704
26705 if((decoded & NM_PAYLOAD_HEADER_ENABLED_MASK) != 0)
26706 dst->payloadHeaderEnabled = true;
26707
26708 if((decoded & NM_EXTENDEDFLAGS1_ENABLED_MASK) != 0) {
26709 decoded = 0;
26710 rv = UA_Byte_decodeBinary(src, offset, &decoded);
26711 UA_CHECK_STATUS(rv, return rv);
26712
26713 dst->publisherIdType = (UA_PublisherIdDatatype)(decoded & NM_PUBLISHER_ID_MASK);
26714 if((decoded & NM_DATASET_CLASSID_ENABLED_MASK) != 0)
26715 dst->dataSetClassIdEnabled = true;
26716
26717 if((decoded & NM_SECURITY_ENABLED_MASK) != 0)
26718 dst->securityEnabled = true;
26719
26720 if((decoded & NM_TIMESTAMP_ENABLED_MASK) != 0)
26721 dst->timestampEnabled = true;
26722
26723 if((decoded & NM_PICOSECONDS_ENABLED_MASK) != 0)
26724 dst->picosecondsEnabled = true;
26725
26726 if((decoded & NM_EXTENDEDFLAGS2_ENABLED_MASK) != 0) {
26727 decoded = 0;
26728 rv = UA_Byte_decodeBinary(src, offset, &decoded);
26729 UA_CHECK_STATUS(rv, return rv);
26730
26731 if((decoded & NM_CHUNK_MESSAGE_MASK) != 0)
26732 dst->chunkMessage = true;
26733
26734 if((decoded & NM_PROMOTEDFIELDS_ENABLED_MASK) != 0)
26735 dst->promotedFieldsEnabled = true;
26736
26737 decoded = decoded & NM_NETWORK_MSG_TYPE_MASK;
26738 decoded = (UA_Byte) (decoded >> NM_SHIFT_LEN);
26739 dst->networkMessageType = (UA_NetworkMessageType)decoded;
26740 }
26741 }
26742
26743 if(dst->publisherIdEnabled) {
26744 switch (dst->publisherIdType) {
26745 case UA_PUBLISHERDATATYPE_BYTE:
26746 rv = UA_Byte_decodeBinary(src, offset, &(dst->publisherId.publisherIdByte));
26747 break;
26748
26749 case UA_PUBLISHERDATATYPE_UINT16:
26750 rv = UA_UInt16_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt16));
26751 break;
26752
26753 case UA_PUBLISHERDATATYPE_UINT32:
26754 rv = UA_UInt32_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt32));
26755 break;
26756
26757 case UA_PUBLISHERDATATYPE_UINT64:
26758 rv = UA_UInt64_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt64));
26759 break;
26760
26761 case UA_PUBLISHERDATATYPE_STRING:
26762 rv = UA_String_decodeBinary(src, offset, &(dst->publisherId.publisherIdString));
26763 break;
26764
26765 default:
26766 rv = UA_STATUSCODE_BADINTERNALERROR;
26767 break;
26768 }
26769 UA_CHECK_STATUS(rv, return rv);
26770 }
26771
26772 if(dst->dataSetClassIdEnabled) {
26773 rv = UA_Guid_decodeBinary(src, offset, &(dst->dataSetClassId));
26774 UA_CHECK_STATUS(rv, return rv);
26775 }
26776 return UA_STATUSCODE_GOOD;
26777}
26778
26779static UA_StatusCode
26780UA_GroupHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
26781 UA_NetworkMessage* dst) {
26782 UA_Byte decoded = 0;
26783 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
26784 UA_CHECK_STATUS(rv, return rv);
26785
26786 if((decoded & GROUP_HEADER_WRITER_GROUPID_ENABLED) != 0)
26787 dst->groupHeader.writerGroupIdEnabled = true;
26788
26789 if((decoded & GROUP_HEADER_GROUP_VERSION_ENABLED) != 0)
26790 dst->groupHeader.groupVersionEnabled = true;
26791
26792 if((decoded & GROUP_HEADER_NM_NUMBER_ENABLED) != 0)
26793 dst->groupHeader.networkMessageNumberEnabled = true;
26794
26795 if((decoded & GROUP_HEADER_SEQUENCE_NUMBER_ENABLED) != 0)
26796 dst->groupHeader.sequenceNumberEnabled = true;
26797
26798 if(dst->groupHeader.writerGroupIdEnabled) {
26799 rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.writerGroupId);
26800 UA_CHECK_STATUS(rv, return rv);
26801 }
26802 if(dst->groupHeader.groupVersionEnabled) {
26803 rv = UA_UInt32_decodeBinary(src, offset, &dst->groupHeader.groupVersion);
26804 UA_CHECK_STATUS(rv, return rv);
26805 }
26806 if(dst->groupHeader.networkMessageNumberEnabled) {
26807 rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.networkMessageNumber);
26808 UA_CHECK_STATUS(rv, return rv);
26809 }
26810 if(dst->groupHeader.sequenceNumberEnabled) {
26811 rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.sequenceNumber);
26812 UA_CHECK_STATUS(rv, return rv);
26813 }
26814 return UA_STATUSCODE_GOOD;
26815}
26816
26817static UA_StatusCode
26818UA_PayloadHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
26819 UA_NetworkMessage* dst) {
26820
26821 if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
26822 return UA_STATUSCODE_BADNOTIMPLEMENTED;
26823
26824 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &dst->payloadHeader.dataSetPayloadHeader.count);
26825 UA_CHECK_STATUS(rv, return rv);
26826
26827 dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds =
26828 (UA_UInt16 *)UA_Array_new(dst->payloadHeader.dataSetPayloadHeader.count,
26829 &UA_TYPES[UA_TYPES_UINT16]);
26830 for (UA_Byte i = 0; i < dst->payloadHeader.dataSetPayloadHeader.count; i++) {
26831 rv = UA_UInt16_decodeBinary(src, offset,
26832 &dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]);
26833 UA_CHECK_STATUS(rv, return rv);
26834 }
26835 return UA_STATUSCODE_GOOD;
26836}
26837
26838static UA_StatusCode
26839UA_ExtendedNetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
26840 UA_NetworkMessage* dst) {
26841 UA_StatusCode rv;
26842
26843 // Timestamp
26844 if(dst->timestampEnabled) {
26845 rv = UA_DateTime_decodeBinary(src, offset, &(dst->timestamp));
26846 UA_CHECK_STATUS(rv, goto error);
26847 }
26848
26849 // Picoseconds
26850 if(dst->picosecondsEnabled) {
26851 rv = UA_UInt16_decodeBinary(src, offset, &(dst->picoseconds));
26852 UA_CHECK_STATUS(rv, goto error);
26853 }
26854
26855 // PromotedFields
26856 if(dst->promotedFieldsEnabled) {
26857 // Size
26858 UA_UInt16 promotedFieldsSize = 0;
26859 rv = UA_UInt16_decodeBinary(src, offset, &promotedFieldsSize);
26860 UA_CHECK_STATUS(rv, goto error);
26861
26862 // promotedFieldsSize: here size in Byte, not the number of objects!
26863 if(promotedFieldsSize > 0) {
26864 // store offset, later compared with promotedFieldsSize
26865 size_t offsetEnd = (*offset) + promotedFieldsSize;
26866
26867 unsigned int counter = 0;
26868 do {
26869 if(counter == 0) {
26870 dst->promotedFields = (UA_Variant*)UA_malloc(UA_TYPES[UA_TYPES_VARIANT].memSize);
26871 UA_CHECK_MEM(dst->promotedFields,
26872 return UA_STATUSCODE_BADOUTOFMEMORY);
26873 // set promotedFieldsSize to the number of objects
26874 dst->promotedFieldsSize = (UA_UInt16) (counter + 1);
26875 } else {
26876 dst->promotedFields = (UA_Variant*)
26877 UA_realloc(dst->promotedFields,
26878 (size_t) UA_TYPES[UA_TYPES_VARIANT].memSize * (counter + 1));
26879 UA_CHECK_MEM(dst->promotedFields,
26880 return UA_STATUSCODE_BADOUTOFMEMORY);
26881 // set promotedFieldsSize to the number of objects
26882 dst->promotedFieldsSize = (UA_UInt16) (counter + 1);
26883 }
26884
26885 UA_Variant_init(&dst->promotedFields[counter]);
26886 rv = UA_Variant_decodeBinary(src, offset, &dst->promotedFields[counter]);
26887 UA_CHECK_STATUS(rv, goto error);
26888
26889 counter++;
26890 } while ((*offset) < offsetEnd);
26891 }
26892 }
26893 return UA_STATUSCODE_GOOD;
26894
26895error:
26896 if (dst->promotedFields) {
26897 UA_free(dst->promotedFields);
26898 }
26899 return rv;
26900}
26901
26902static UA_StatusCode
26903UA_SecurityHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
26904 UA_NetworkMessage* dst) {
26905 UA_Byte decoded = 0;
26906 // SecurityFlags
26907 decoded = 0;
26908 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
26909 UA_CHECK_STATUS(rv, return rv);
26910
26911 if((decoded & SECURITY_HEADER_NM_SIGNED) != 0)
26912 dst->securityHeader.networkMessageSigned = true;
26913
26914 if((decoded & SECURITY_HEADER_NM_ENCRYPTED) != 0)
26915 dst->securityHeader.networkMessageEncrypted = true;
26916
26917 if((decoded & SECURITY_HEADER_SEC_FOOTER_ENABLED) != 0)
26918 dst->securityHeader.securityFooterEnabled = true;
26919
26920 if((decoded & SECURITY_HEADER_FORCE_KEY_RESET) != 0)
26921 dst->securityHeader.forceKeyReset = true;
26922
26923 // SecurityTokenId
26924 rv = UA_UInt32_decodeBinary(src, offset, &dst->securityHeader.securityTokenId);
26925 UA_CHECK_STATUS(rv, return rv);
26926
26927 // NonceLength
26928 UA_Byte nonceLength;
26929 rv = UA_Byte_decodeBinary(src, offset, &nonceLength);
26930 UA_CHECK_STATUS(rv, return rv);
26931
26932 // MessageNonce
26933 if(nonceLength > 0) {
26934 //TODO: check for memory leaks
26935 rv = UA_ByteString_allocBuffer(&dst->securityHeader.messageNonce, nonceLength);
26936 UA_CHECK_STATUS(rv, return rv);
26937 for (UA_Byte i = 0; i < nonceLength; i++) {
26938 rv = UA_Byte_decodeBinary(src, offset,
26939 &dst->securityHeader.messageNonce.data[i]);
26940 UA_CHECK_STATUS(rv, return rv);
26941 }
26942 }
26943 // SecurityFooterSize
26944 if(dst->securityHeader.securityFooterEnabled) {
26945 rv = UA_UInt16_decodeBinary(src, offset, &dst->securityHeader.securityFooterSize);
26946 UA_CHECK_STATUS(rv, return rv);
26947 }
26948 return UA_STATUSCODE_GOOD;
26949}
26950
26951UA_StatusCode
26952UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
26953
26954 UA_StatusCode rv = UA_NetworkMessageHeader_decodeBinary(src, offset, dst);
26955 UA_CHECK_STATUS(rv, return rv);
26956
26957 if (dst->groupHeaderEnabled) {
26958 rv = UA_GroupHeader_decodeBinary(src, offset, dst);
26959 UA_CHECK_STATUS(rv, return rv);
26960 }
26961
26962 if (dst->payloadHeaderEnabled) {
26963 rv = UA_PayloadHeader_decodeBinary(src, offset, dst);
26964 UA_CHECK_STATUS(rv, return rv);
26965 }
26966
26967 if (dst->securityEnabled) {
26968 rv = UA_SecurityHeader_decodeBinary(src, offset, dst);
26969 UA_CHECK_STATUS(rv, return rv);
26970 }
26971
26972 rv = UA_ExtendedNetworkMessageHeader_decodeBinary(src, offset, dst);
26973 UA_CHECK_STATUS(rv, return rv);
26974
26975 return UA_STATUSCODE_GOOD;
26976}
26977
26978UA_StatusCode
26979UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
26980
26981 // Payload
26982 if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
26983 return UA_STATUSCODE_BADNOTIMPLEMENTED;
26984
26985 UA_StatusCode rv;
26986
26987 UA_Byte count = 1;
26988 if(dst->payloadHeaderEnabled) {
26989 count = dst->payloadHeader.dataSetPayloadHeader.count;
26990 if(count > 1) {
26991 dst->payload.dataSetPayload.sizes = (UA_UInt16 *)UA_Array_new(count, &UA_TYPES[UA_TYPES_UINT16]);
26992 for (UA_Byte i = 0; i < count; i++) {
26993 rv = UA_UInt16_decodeBinary(src, offset, &(dst->payload.dataSetPayload.sizes[i]));
26994 UA_CHECK_STATUS(rv, return rv);
26995 }
26996 }
26997 }
26998
26999 dst->payload.dataSetPayload.dataSetMessages = (UA_DataSetMessage*)
27000 UA_calloc(count, sizeof(UA_DataSetMessage));
27001 UA_CHECK_MEM(dst->payload.dataSetPayload.dataSetMessages,
27002 return UA_STATUSCODE_BADOUTOFMEMORY);
27003
27004 if(count == 1)
27005 rv = UA_DataSetMessage_decodeBinary(src, offset,
27006 &(dst->payload.dataSetPayload.dataSetMessages[0]),
27007 0);
27008 else {
27009 for(UA_Byte i = 0; i < count; i++) {
27010 rv = UA_DataSetMessage_decodeBinary(src, offset,
27011 &(dst->payload.dataSetPayload.dataSetMessages[i]),
27012 dst->payload.dataSetPayload.sizes[i]);
27013 }
27014 }
27015 UA_CHECK_STATUS(rv, return rv);
27016
27017 return UA_STATUSCODE_GOOD;
27018
27019 /**
27020 * TODO: check if making the cleanup to free its own allocated memory is better,
27021 * currently the free happens in a parent context
27022 */
27023 // error:
27024 // if (dst->payload.dataSetPayload.dataSetMessages) {
27025 // UA_free(dst->payload.dataSetPayload.dataSetMessages);
27026 // }
27027 // return rv;
27028}
27029
27030UA_StatusCode
27031UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
27032
27033 if (dst->securityEnabled) {
27034 // SecurityFooter
27035 if(dst->securityHeader.securityFooterEnabled &&
27036 (dst->securityHeader.securityFooterSize > 0)) {
27037 UA_StatusCode rv = UA_ByteString_allocBuffer(&dst->securityFooter,
27038 dst->securityHeader.securityFooterSize);
27039 UA_CHECK_STATUS(rv, return rv);
27040
27041 for(UA_UInt16 i = 0; i < dst->securityHeader.securityFooterSize; i++) {
27042 rv = UA_Byte_decodeBinary(src, offset, &(dst->securityFooter.data[i]));
27043 UA_CHECK_STATUS(rv, return rv);
27044 }
27045 }
27046 }
27047 return UA_STATUSCODE_GOOD;
27048}
27049
27050UA_StatusCode
27051UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
27052 UA_NetworkMessage* dst) {
27053
27054 UA_StatusCode rv = UA_STATUSCODE_GOOD;
27055
27056 /* headers only need to be decoded when not in encryption mode
27057 * because headers are already decoded when encryption mode is enabled
27058 * to check for security parameters and decrypt/verify
27059 *
27060 * TODO: check if there is a workaround to use this function
27061 * also when encryption is enabled
27062 */
27063 // #ifndef UA_ENABLE_PUBSUB_ENCRYPTION
27064 // if (*offset == 0) {
27065 // rv = UA_NetworkMessage_decodeHeaders(src, offset, dst);
27066 // UA_CHECK_STATUS(rv, return rv);
27067 // }
27068 // #endif
27069
27070 rv = UA_NetworkMessage_decodeHeaders(src, offset, dst);
27071 UA_CHECK_STATUS(rv, return rv);
27072
27073 rv = UA_NetworkMessage_decodePayload(src, offset, dst);
27074 UA_CHECK_STATUS(rv, return rv);
27075
27076 rv = UA_NetworkMessage_decodeFooters(src, offset, dst);
27077 UA_CHECK_STATUS(rv, return rv);
27078
27079 return UA_STATUSCODE_GOOD;
27080}
27081
27082static UA_Boolean
27083increaseOffsetArray(UA_NetworkMessageOffsetBuffer *offsetBuffer) {
27084 UA_NetworkMessageOffset *tmpOffsets = (UA_NetworkMessageOffset *)
27085 UA_realloc(offsetBuffer->offsets, sizeof(UA_NetworkMessageOffset) * (offsetBuffer->offsetsSize + (size_t)1));
27086 UA_CHECK_MEM(tmpOffsets, return false);
27087
27088 offsetBuffer->offsets = tmpOffsets;
27089 offsetBuffer->offsetsSize++;
27090 return true;
27091}
27092
27093size_t
27094UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer) {
27095 size_t retval = 0;
27096 UA_Byte byte = 0;
27097 size_t size = UA_Byte_calcSizeBinary(&byte); // UADPVersion + UADPFlags
27098 if(UA_NetworkMessage_ExtendedFlags1Enabled(p)) {
27099 size += UA_Byte_calcSizeBinary(&byte);
27100 if(UA_NetworkMessage_ExtendedFlags2Enabled(p))
27101 size += UA_Byte_calcSizeBinary(&byte);
27102 }
27103
27104 if(p->publisherIdEnabled) {
27105 if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
27106 size_t pos = offsetBuffer->offsetsSize;
27107 if(!increaseOffsetArray(offsetBuffer))
27108 return 0;
27109
27110 offsetBuffer->offsets[pos].offset = size;
27111 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PUBLISHERID;
27112 }
27113 switch (p->publisherIdType) {
27114 case UA_PUBLISHERDATATYPE_BYTE:
27115 size += UA_Byte_calcSizeBinary(&p->publisherId.publisherIdByte);
27116 break;
27117
27118 case UA_PUBLISHERDATATYPE_UINT16:
27119 size += UA_UInt16_calcSizeBinary(&p->publisherId.publisherIdUInt16);
27120 break;
27121
27122 case UA_PUBLISHERDATATYPE_UINT32:
27123 size += UA_UInt32_calcSizeBinary(&p->publisherId.publisherIdUInt32);
27124 break;
27125
27126 case UA_PUBLISHERDATATYPE_UINT64:
27127 size += UA_UInt64_calcSizeBinary(&p->publisherId.publisherIdUInt64);
27128 break;
27129
27130 case UA_PUBLISHERDATATYPE_STRING:
27131 size += UA_String_calcSizeBinary(&p->publisherId.publisherIdString);
27132 break;
27133 }
27134 }
27135
27136 if(p->dataSetClassIdEnabled)
27137 size += UA_Guid_calcSizeBinary(&p->dataSetClassId);
27138
27139 // Group Header
27140 if(p->groupHeaderEnabled) {
27141 size += UA_Byte_calcSizeBinary(&byte);
27142
27143 if(p->groupHeader.writerGroupIdEnabled) {
27144 if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
27145 size_t pos = offsetBuffer->offsetsSize;
27146 if(!increaseOffsetArray(offsetBuffer))
27147 return 0;
27148
27149 offsetBuffer->offsets[pos].offset = size;
27150 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_WRITERGROUPID;
27151 }
27152 size += UA_UInt16_calcSizeBinary(&p->groupHeader.writerGroupId);
27153 }
27154
27155 if(p->groupHeader.groupVersionEnabled)
27156 size += UA_UInt32_calcSizeBinary(&p->groupHeader.groupVersion);
27157
27158 if(p->groupHeader.networkMessageNumberEnabled) {
27159 size += UA_UInt16_calcSizeBinary(&p->groupHeader.networkMessageNumber);
27160 }
27161
27162 if(p->groupHeader.sequenceNumberEnabled){
27163 if(offsetBuffer){
27164 size_t pos = offsetBuffer->offsetsSize;
27165 if(!increaseOffsetArray(offsetBuffer))
27166 return 0;
27167 offsetBuffer->offsets[pos].offset = size;
27168 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27169 UA_Variant_setScalarCopy(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27170 &p->groupHeader.sequenceNumber, &UA_TYPES[UA_TYPES_UINT16]);
27171 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER;
27172 }
27173 size += UA_UInt16_calcSizeBinary(&p->groupHeader.sequenceNumber);
27174 }
27175 }
27176
27177 // Payload Header
27178 if(p->payloadHeaderEnabled) {
27179 if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
27180 size += UA_Byte_calcSizeBinary(&p->payloadHeader.dataSetPayloadHeader.count);
27181 if(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != NULL) {
27182 if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
27183 size_t pos = offsetBuffer->offsetsSize;
27184 if(!increaseOffsetArray(offsetBuffer))
27185 return 0;
27186 offsetBuffer->offsets[pos].offset = size;
27187 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_DATASETWRITERID;
27188 }
27189 size += UA_UInt16_calcSizeBinary(&p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]) *
27190 p->payloadHeader.dataSetPayloadHeader.count;
27191 } else {
27192 return 0; /* no dataSetWriterIds given! */
27193 }
27194 } else {
27195 // not implemented
27196 }
27197 }
27198
27199 if(p->timestampEnabled) {
27200 if(offsetBuffer){
27201 size_t pos = offsetBuffer->offsetsSize;
27202 if(!increaseOffsetArray(offsetBuffer))
27203 return 0;
27204 offsetBuffer->offsets[pos].offset = size;
27205 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_TIMESTAMP;
27206 }
27207 size += UA_DateTime_calcSizeBinary(&p->timestamp);
27208 }
27209
27210 if(p->picosecondsEnabled){
27211 if (offsetBuffer) {
27212 size_t pos = offsetBuffer->offsetsSize;
27213 if(!increaseOffsetArray(offsetBuffer))
27214 return 0;
27215 offsetBuffer->offsets[pos].offset = size;
27216 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS;
27217 }
27218 size += UA_UInt16_calcSizeBinary(&p->picoseconds);
27219 }
27220
27221 if(p->promotedFieldsEnabled) {
27222 size += UA_UInt16_calcSizeBinary(&p->promotedFieldsSize);
27223 for (UA_UInt16 i = 0; i < p->promotedFieldsSize; i++)
27224 size += UA_Variant_calcSizeBinary(&p->promotedFields[i]);
27225 }
27226
27227 if(p->securityEnabled) {
27228 size += UA_Byte_calcSizeBinary(&byte);
27229 size += UA_UInt32_calcSizeBinary(&p->securityHeader.securityTokenId);
27230 size += 1; /* UA_Byte_calcSizeBinary(&p->securityHeader.nonceLength); */
27231 size += p->securityHeader.messageNonce.length;
27232 if(p->securityHeader.securityFooterEnabled)
27233 size += UA_UInt16_calcSizeBinary(&p->securityHeader.securityFooterSize);
27234 }
27235
27236 if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
27237 UA_Byte count = 1;
27238 if(p->payloadHeaderEnabled) {
27239 count = p->payloadHeader.dataSetPayloadHeader.count;
27240 if(count > 1)
27241 size += UA_UInt16_calcSizeBinary(&(p->payload.dataSetPayload.sizes[0])) * count;
27242 }
27243
27244 for (size_t i = 0; i < count; i++) {
27245 if (offsetBuffer)
27246 UA_DataSetMessage_calcSizeBinary(&(p->payload.dataSetPayload.dataSetMessages[i]), offsetBuffer,
27247 size);
27248 size += UA_DataSetMessage_calcSizeBinary(&(p->payload.dataSetPayload.dataSetMessages[i]), NULL, 0);
27249 }
27250 }
27251
27252 if(p->securityEnabled) {
27253 if(p->securityHeader.securityFooterEnabled)
27254 size += p->securityHeader.securityFooterSize;
27255 }
27256
27257 retval = size;
27258 return retval;
27259}
27260
27261void
27262UA_NetworkMessage_clear(UA_NetworkMessage* p) {
27263 if(p->promotedFieldsEnabled)
27264 UA_Array_delete(p->promotedFields, p->promotedFieldsSize, &UA_TYPES[UA_TYPES_VARIANT]);
27265
27266 UA_ByteString_clear(&p->securityHeader.messageNonce);
27267
27268 if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
27269 if(p->payloadHeaderEnabled) {
27270 if(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != NULL) {
27271 UA_Array_delete(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds,
27272 p->payloadHeader.dataSetPayloadHeader.count, &UA_TYPES[UA_TYPES_UINT16]);
27273 }
27274 if(p->payload.dataSetPayload.sizes != NULL) {
27275 UA_Array_delete(p->payload.dataSetPayload.sizes,
27276 p->payloadHeader.dataSetPayloadHeader.count, &UA_TYPES[UA_TYPES_UINT16]);
27277 }
27278 }
27279
27280 if(p->payload.dataSetPayload.dataSetMessages) {
27281 UA_Byte count = 1;
27282 if(p->payloadHeaderEnabled)
27283 count = p->payloadHeader.dataSetPayloadHeader.count;
27284
27285 for(size_t i = 0; i < count; i++)
27286 UA_DataSetMessage_clear(&(p->payload.dataSetPayload.dataSetMessages[i]));
27287
27288 UA_free(p->payload.dataSetPayload.dataSetMessages);
27289 }
27290 }
27291
27292 if(p->securityHeader.securityFooterEnabled && (p->securityHeader.securityFooterSize > 0))
27293 UA_ByteString_clear(&p->securityFooter);
27294
27295 if(p->messageIdEnabled){
27296 UA_String_clear(&p->messageId);
27297 }
27298
27299 if(p->publisherIdEnabled && p->publisherIdType == UA_PUBLISHERDATATYPE_STRING){
27300 UA_String_clear(&p->publisherId.publisherIdString);
27301 }
27302
27303 memset(p, 0, sizeof(UA_NetworkMessage));
27304}
27305
27306UA_Boolean
27307UA_NetworkMessage_ExtendedFlags1Enabled(const UA_NetworkMessage* src) {
27308 UA_Boolean retval = false;
27309
27310 if((src->publisherIdType != UA_PUBLISHERDATATYPE_BYTE)
27311 || src->dataSetClassIdEnabled
27312 || src->securityEnabled
27313 || src->timestampEnabled
27314 || src->picosecondsEnabled
27315 || UA_NetworkMessage_ExtendedFlags2Enabled(src))
27316 {
27317 retval = true;
27318 }
27319
27320 return retval;
27321}
27322
27323UA_Boolean
27324UA_NetworkMessage_ExtendedFlags2Enabled(const UA_NetworkMessage* src) {
27325 if(src->chunkMessage || src->promotedFieldsEnabled ||
27326 src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
27327 return true;
27328 return false;
27329}
27330
27331UA_Boolean
27332UA_DataSetMessageHeader_DataSetFlags2Enabled(const UA_DataSetMessageHeader* src) {
27333 if(src->dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME ||
27334 src->timestampEnabled || src->picoSecondsIncluded)
27335 return true;
27336 return false;
27337}
27338
27339UA_StatusCode
27340UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src, UA_Byte **bufPos,
27341 const UA_Byte *bufEnd) {
27342 UA_Byte v;
27343 // DataSetFlags1
27344 v = (UA_Byte)src->fieldEncoding;
27345 // shift left 1 bit
27346 v = (UA_Byte)(v << DS_MH_SHIFT_LEN);
27347
27348 if(src->dataSetMessageValid)
27349 v |= DS_MESSAGEHEADER_DS_MSG_VALID;
27350
27351 if(src->dataSetMessageSequenceNrEnabled)
27352 v |= DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK;
27353
27354 if(src->statusEnabled)
27355 v |= DS_MESSAGEHEADER_STATUS_ENABLED_MASK;
27356
27357 if(src->configVersionMajorVersionEnabled)
27358 v |= DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK;
27359
27360 if(src->configVersionMinorVersionEnabled)
27361 v |= DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK;
27362
27363 if(UA_DataSetMessageHeader_DataSetFlags2Enabled(src))
27364 v |= DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK;
27365
27366 UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
27367 UA_CHECK_STATUS(rv, return rv);
27368
27369 // DataSetFlags2
27370 if(UA_DataSetMessageHeader_DataSetFlags2Enabled(src)) {
27371 v = (UA_Byte)src->dataSetMessageType;
27372
27373 if(src->timestampEnabled)
27374 v |= DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK;
27375
27376 if(src->picoSecondsIncluded)
27377 v |= DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK;
27378
27379 rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
27380 UA_CHECK_STATUS(rv, return rv);
27381 }
27382
27383 // DataSetMessageSequenceNr
27384 if(src->dataSetMessageSequenceNrEnabled) {
27385 rv = UA_UInt16_encodeBinary(&src->dataSetMessageSequenceNr, bufPos, bufEnd);
27386 UA_CHECK_STATUS(rv, return rv);
27387 }
27388
27389 // Timestamp
27390 if(src->timestampEnabled) {
27391 rv = UA_DateTime_encodeBinary(&(src->timestamp), bufPos, bufEnd); /* UtcTime */
27392 UA_CHECK_STATUS(rv, return rv);
27393 }
27394
27395 // PicoSeconds
27396 if(src->picoSecondsIncluded) {
27397 rv = UA_UInt16_encodeBinary(&(src->picoSeconds), bufPos, bufEnd);
27398 UA_CHECK_STATUS(rv, return rv);
27399 }
27400
27401 // Status
27402 if(src->statusEnabled) {
27403 rv = UA_UInt16_encodeBinary(&(src->status), bufPos, bufEnd);
27404 UA_CHECK_STATUS(rv, return rv);
27405 }
27406
27407 // ConfigVersionMajorVersion
27408 if(src->configVersionMajorVersionEnabled) {
27409 rv = UA_UInt32_encodeBinary(&(src->configVersionMajorVersion), bufPos, bufEnd);
27410 UA_CHECK_STATUS(rv, return rv);
27411 }
27412
27413 // ConfigVersionMinorVersion
27414 if(src->configVersionMinorVersionEnabled) {
27415 rv = UA_UInt32_encodeBinary(&(src->configVersionMinorVersion), bufPos, bufEnd);
27416 UA_CHECK_STATUS(rv, return rv);
27417 }
27418
27419 return UA_STATUSCODE_GOOD;
27420}
27421
27422#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
27423
27424UA_StatusCode
27425UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode securityMode,
27426 UA_PubSubSecurityPolicy *policy, void *policyContext,
27427 UA_Byte *messageStart, UA_Byte *encryptStart,
27428 UA_Byte *sigStart) {
27429 UA_StatusCode res = UA_STATUSCODE_GOOD;
27430
27431 /* Encrypt the payload */
27432 if(securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
27433 /* Set the temporary MessageNonce in the SecurityPolicy */
27434 res = policy->setMessageNonce(policyContext, &nm->securityHeader.messageNonce);
27435 UA_CHECK_STATUS(res, return res);
27436
27437 /* The encryption is done in-place, no need to encode again */
27438 UA_ByteString encryptBuf;
27439 encryptBuf.data = encryptStart;
27440 encryptBuf.length = (uintptr_t)sigStart - (uintptr_t)encryptStart;
27441 res = policy->symmetricModule.cryptoModule.encryptionAlgorithm.
27442 encrypt(policyContext, &encryptBuf);
27443 UA_CHECK_STATUS(res, return res);
27444 }
27445
27446 /* Sign the entire message */
27447 if(securityMode == UA_MESSAGESECURITYMODE_SIGN ||
27448 securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
27449 UA_ByteString sigBuf;
27450 sigBuf.length = (uintptr_t)sigStart - (uintptr_t)messageStart;
27451 sigBuf.data = messageStart;
27452 size_t sigSize = policy->symmetricModule.cryptoModule.
27453 signatureAlgorithm.getLocalSignatureSize(policyContext);
27454 UA_ByteString sig = {sigSize, sigStart};
27455 res = policy->symmetricModule.cryptoModule.
27456 signatureAlgorithm.sign(policyContext, &sigBuf, &sig);
27457 }
27458
27459 return res;
27460}
27461#endif
27462
27463UA_StatusCode
27464UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
27465 UA_DataSetMessageHeader* dst) {
27466 memset(dst, 0, sizeof(UA_DataSetMessageHeader));
27467 UA_Byte v = 0;
27468 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &v);
27469 UA_CHECK_STATUS(rv, return rv);
27470
27471 UA_Byte v2 = v & DS_MESSAGEHEADER_FIELD_ENCODING_MASK;
27472 v2 = (UA_Byte)(v2 >> DS_MH_SHIFT_LEN);
27473 dst->fieldEncoding = (UA_FieldEncoding)v2;
27474
27475 if((v & DS_MESSAGEHEADER_DS_MSG_VALID) != 0)
27476 dst->dataSetMessageValid = true;
27477
27478 if((v & DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK) != 0)
27479 dst->dataSetMessageSequenceNrEnabled = true;
27480
27481 if((v & DS_MESSAGEHEADER_STATUS_ENABLED_MASK) != 0)
27482 dst->statusEnabled = true;
27483
27484 if((v & DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK) != 0)
27485 dst->configVersionMajorVersionEnabled = true;
27486
27487 if((v & DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK) != 0)
27488 dst->configVersionMinorVersionEnabled = true;
27489
27490 if((v & DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK) != 0) {
27491 v = 0;
27492 rv = UA_Byte_decodeBinary(src, offset, &v);
27493 UA_CHECK_STATUS(rv, return rv);
27494
27495 dst->dataSetMessageType = (UA_DataSetMessageType)(v & DS_MESSAGEHEADER_DS_MESSAGE_TYPE_MASK);
27496
27497 if((v & DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK) != 0)
27498 dst->timestampEnabled = true;
27499
27500 if((v & DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK) != 0)
27501 dst->picoSecondsIncluded = true;
27502 } else {
27503 dst->dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
27504 dst->picoSecondsIncluded = false;
27505 }
27506
27507 if(dst->dataSetMessageSequenceNrEnabled) {
27508 rv = UA_UInt16_decodeBinary(src, offset, &dst->dataSetMessageSequenceNr);
27509 UA_CHECK_STATUS(rv, return rv);
27510 } else {
27511 dst->dataSetMessageSequenceNr = 0;
27512 }
27513
27514 if(dst->timestampEnabled) {
27515 rv = UA_DateTime_decodeBinary(src, offset, &dst->timestamp); /* UtcTime */
27516 UA_CHECK_STATUS(rv, return rv);
27517 } else {
27518 dst->timestamp = 0;
27519 }
27520
27521 if(dst->picoSecondsIncluded) {
27522 rv = UA_UInt16_decodeBinary(src, offset, &dst->picoSeconds);
27523 UA_CHECK_STATUS(rv, return rv);
27524 } else {
27525 dst->picoSeconds = 0;
27526 }
27527
27528 if(dst->statusEnabled) {
27529 rv = UA_UInt16_decodeBinary(src, offset, &dst->status);
27530 UA_CHECK_STATUS(rv, return rv);
27531 } else {
27532 dst->status = 0;
27533 }
27534
27535 if(dst->configVersionMajorVersionEnabled) {
27536 rv = UA_UInt32_decodeBinary(src, offset, &dst->configVersionMajorVersion);
27537 UA_CHECK_STATUS(rv, return rv);
27538 } else {
27539 dst->configVersionMajorVersion = 0;
27540 }
27541
27542 if(dst->configVersionMinorVersionEnabled) {
27543 rv = UA_UInt32_decodeBinary(src, offset, &dst->configVersionMinorVersion);
27544 UA_CHECK_STATUS(rv, return rv);
27545 } else {
27546 dst->configVersionMinorVersion = 0;
27547 }
27548
27549 return UA_STATUSCODE_GOOD;
27550}
27551
27552size_t
27553UA_DataSetMessageHeader_calcSizeBinary(const UA_DataSetMessageHeader* p) {
27554 UA_Byte byte = 0;
27555 size_t size = UA_Byte_calcSizeBinary(&byte); // DataSetMessage Type + Flags
27556 if(UA_DataSetMessageHeader_DataSetFlags2Enabled(p))
27557 size += UA_Byte_calcSizeBinary(&byte);
27558
27559 if(p->dataSetMessageSequenceNrEnabled)
27560 size += UA_UInt16_calcSizeBinary(&p->dataSetMessageSequenceNr);
27561
27562 if(p->timestampEnabled)
27563 size += UA_DateTime_calcSizeBinary(&p->timestamp); /* UtcTime */
27564
27565 if(p->picoSecondsIncluded)
27566 size += UA_UInt16_calcSizeBinary(&p->picoSeconds);
27567
27568 if(p->statusEnabled)
27569 size += UA_UInt16_calcSizeBinary(&p->status);
27570
27571 if(p->configVersionMajorVersionEnabled)
27572 size += UA_UInt32_calcSizeBinary(&p->configVersionMajorVersion);
27573
27574 if(p->configVersionMinorVersionEnabled)
27575 size += UA_UInt32_calcSizeBinary(&p->configVersionMinorVersion);
27576
27577 return size;
27578}
27579
27580UA_StatusCode
27581UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
27582 const UA_Byte *bufEnd) {
27583 UA_StatusCode rv = UA_DataSetMessageHeader_encodeBinary(&src->header, bufPos, bufEnd);
27584 UA_CHECK_STATUS(rv, return rv);
27585
27586 if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
27587 if(src->header.fieldEncoding != UA_FIELDENCODING_RAWDATA) {
27588 rv = UA_UInt16_encodeBinary(&(src->data.keyFrameData.fieldCount), bufPos, bufEnd);
27589 UA_CHECK_STATUS(rv, return rv);
27590 }
27591 if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27592 for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
27593 rv = UA_Variant_encodeBinary(&(src->data.keyFrameData.dataSetFields[i].value), bufPos, bufEnd);
27594 UA_CHECK_STATUS(rv, return rv);
27595 }
27596 } else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
27597 for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
27598 rv = UA_encodeBinaryInternal(src->data.keyFrameData.dataSetFields[i].value.data,
27599 src->data.keyFrameData.dataSetFields[i].value.type,
27600 bufPos, &bufEnd, NULL, NULL);
27601 UA_CHECK_STATUS(rv, return rv);
27602 }
27603 } else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27604 for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
27605 rv = UA_DataValue_encodeBinary(&(src->data.keyFrameData.dataSetFields[i]), bufPos, bufEnd);
27606 UA_CHECK_STATUS(rv, return rv);
27607 }
27608 }
27609 } else if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
27610 // Encode Delta Frame
27611 // Here the FieldCount is always present
27612 rv = UA_UInt16_encodeBinary(&(src->data.keyFrameData.fieldCount), bufPos, bufEnd);
27613 UA_CHECK_STATUS(rv, return rv);
27614
27615 if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27616 for (UA_UInt16 i = 0; i < src->data.deltaFrameData.fieldCount; i++) {
27617 rv = UA_UInt16_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldIndex), bufPos, bufEnd);
27618 UA_CHECK_STATUS(rv, return rv);
27619
27620 rv = UA_Variant_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldValue.value), bufPos, bufEnd);
27621 UA_CHECK_STATUS(rv, return rv);
27622 }
27623 } else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
27624 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27625 } else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27626 for (UA_UInt16 i = 0; i < src->data.deltaFrameData.fieldCount; i++) {
27627 rv = UA_UInt16_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldIndex), bufPos, bufEnd);
27628 UA_CHECK_STATUS(rv, return rv);
27629
27630 rv = UA_DataValue_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldValue), bufPos, bufEnd);
27631 UA_CHECK_STATUS(rv, return rv);
27632 }
27633 }
27634 } else if(src->header.dataSetMessageType != UA_DATASETMESSAGE_KEEPALIVE) {
27635 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27636 }
27637
27638 /* Keep-Alive Message contains no Payload Data */
27639 return UA_STATUSCODE_GOOD;
27640}
27641
27642UA_StatusCode
27643UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataSetMessage* dst, UA_UInt16 dsmSize) {
27644 size_t initialOffset = *offset;
27645 memset(dst, 0, sizeof(UA_DataSetMessage));
27646 UA_StatusCode rv = UA_DataSetMessageHeader_decodeBinary(src, offset, &dst->header);
27647 UA_CHECK_STATUS(rv, return rv);
27648
27649 if(dst->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
27650 switch(dst->header.fieldEncoding) {
27651 case UA_FIELDENCODING_VARIANT:
27652 {
27653 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.keyFrameData.fieldCount);
27654 UA_CHECK_STATUS(rv, return rv);
27655 dst->data.keyFrameData.dataSetFields =
27656 (UA_DataValue *)UA_Array_new(dst->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
27657 for (UA_UInt16 i = 0; i < dst->data.keyFrameData.fieldCount; i++) {
27658 UA_DataValue_init(&dst->data.keyFrameData.dataSetFields[i]);
27659 rv = UA_Variant_decodeBinary(src, offset, &dst->data.keyFrameData.dataSetFields[i].value);
27660 UA_CHECK_STATUS(rv, return rv);
27661
27662 dst->data.keyFrameData.dataSetFields[i].hasValue = true;
27663 }
27664 break;
27665 }
27666 case UA_FIELDENCODING_DATAVALUE:
27667 {
27668 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.keyFrameData.fieldCount);
27669 UA_CHECK_STATUS(rv, return rv);
27670 dst->data.keyFrameData.dataSetFields =
27671 (UA_DataValue *)UA_Array_new(dst->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
27672 for (UA_UInt16 i = 0; i < dst->data.keyFrameData.fieldCount; i++) {
27673 rv = UA_DataValue_decodeBinary(src, offset, &(dst->data.keyFrameData.dataSetFields[i]));
27674 UA_CHECK_STATUS(rv, return rv);
27675 }
27676 break;
27677 }
27678 case UA_FIELDENCODING_RAWDATA:
27679 {
27680 dst->data.keyFrameData.rawFields.data = &src->data[*offset];
27681 dst->data.keyFrameData.rawFields.length = dsmSize;
27682 if(dsmSize == 0){
27683 //TODO calculate the length of the DSM-Payload for a single DSM
27684 //Problem: Size is not set and MetaData information are needed.
27685 //Increase offset to avoid endless chunk loop. Needs to be fixed when
27686 //pubsub security footer and signatur is enabled.
27687 *offset += 1500;
27688 } else {
27689 *offset += (dsmSize - (*offset - initialOffset));
27690 }
27691 break;
27692 }
27693 default:
27694 return UA_STATUSCODE_BADINTERNALERROR;
27695 }
27696 } else if(dst->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
27697 switch(dst->header.fieldEncoding) {
27698 case UA_FIELDENCODING_VARIANT: {
27699 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.fieldCount);
27700 UA_CHECK_STATUS(rv, return rv);
27701 size_t memsize = sizeof(UA_DataSetMessage_DeltaFrameField) * dst->data.deltaFrameData.fieldCount;
27702 dst->data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)UA_malloc(memsize);
27703 for (UA_UInt16 i = 0; i < dst->data.deltaFrameData.fieldCount; i++) {
27704 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldIndex);
27705 UA_CHECK_STATUS(rv, return rv);
27706
27707 UA_DataValue_init(&dst->data.deltaFrameData.deltaFrameFields[i].fieldValue);
27708 rv = UA_Variant_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldValue.value);
27709 UA_CHECK_STATUS(rv, return rv);
27710
27711 dst->data.deltaFrameData.deltaFrameFields[i].fieldValue.hasValue = true;
27712 }
27713 break;
27714 }
27715 case UA_FIELDENCODING_DATAVALUE: {
27716 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.fieldCount);
27717 UA_CHECK_STATUS(rv, return rv);
27718 size_t memsize = sizeof(UA_DataSetMessage_DeltaFrameField) * dst->data.deltaFrameData.fieldCount;
27719 dst->data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)UA_malloc(memsize);
27720 for (UA_UInt16 i = 0; i < dst->data.deltaFrameData.fieldCount; i++) {
27721 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldIndex);
27722 UA_CHECK_STATUS(rv, return rv);
27723
27724 rv = UA_DataValue_decodeBinary(src, offset, &(dst->data.deltaFrameData.deltaFrameFields[i].fieldValue));
27725 UA_CHECK_STATUS(rv, return rv);
27726 }
27727 break;
27728 }
27729 case UA_FIELDENCODING_RAWDATA: {
27730 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27731 }
27732 default:
27733 return UA_STATUSCODE_BADINTERNALERROR;
27734 }
27735 } else if(dst->header.dataSetMessageType != UA_DATASETMESSAGE_KEEPALIVE) {
27736 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27737 }
27738
27739 /* Keep-Alive Message contains no Payload Data */
27740 return UA_STATUSCODE_GOOD;
27741}
27742
27743size_t
27744UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBuffer *offsetBuffer, size_t currentOffset) {
27745 size_t size = currentOffset;
27746
27747 if (offsetBuffer) {
27748 size_t pos = offsetBuffer->offsetsSize;
27749 if(!increaseOffsetArray(offsetBuffer))
27750 return 0;
27751 offsetBuffer->offsets[pos].offset = size;
27752 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27753 UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27754 &p->header.fieldEncoding, &UA_TYPES[UA_TYPES_UINT32]);
27755 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING;
27756 }
27757
27758 UA_Byte byte = 0;
27759 size += UA_Byte_calcSizeBinary(&byte); // DataSetMessage Type + Flags
27760 if(UA_DataSetMessageHeader_DataSetFlags2Enabled(&p->header))
27761 size += UA_Byte_calcSizeBinary(&byte);
27762
27763 if(p->header.dataSetMessageSequenceNrEnabled) {
27764 if (offsetBuffer) {
27765 size_t pos = offsetBuffer->offsetsSize;
27766 if(!increaseOffsetArray(offsetBuffer))
27767 return 0;
27768 offsetBuffer->offsets[pos].offset = size;
27769 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27770 UA_Variant_setScalarCopy(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27771 &p->header.dataSetMessageSequenceNr, &UA_TYPES[UA_TYPES_UINT16]);
27772 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER;
27773 }
27774 size += UA_UInt16_calcSizeBinary(&p->header.dataSetMessageSequenceNr);
27775 }
27776
27777 if(p->header.timestampEnabled)
27778 size += UA_DateTime_calcSizeBinary(&p->header.timestamp); /* UtcTime */
27779
27780 if(p->header.picoSecondsIncluded)
27781 size += UA_UInt16_calcSizeBinary(&p->header.picoSeconds);
27782
27783 if(p->header.statusEnabled)
27784 size += UA_UInt16_calcSizeBinary(&p->header.status);
27785
27786 if(p->header.configVersionMajorVersionEnabled)
27787 size += UA_UInt32_calcSizeBinary(&p->header.configVersionMajorVersion);
27788
27789 if(p->header.configVersionMinorVersionEnabled)
27790 size += UA_UInt32_calcSizeBinary(&p->header.configVersionMinorVersion);
27791
27792 if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
27793 if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA){
27794 size += UA_calcSizeBinary(&p->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_UINT16]);
27795 }
27796 if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27797 for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++){
27798 if (offsetBuffer) {
27799 size_t pos = offsetBuffer->offsetsSize;
27800 if(!increaseOffsetArray(offsetBuffer))
27801 return 0;
27802 offsetBuffer->offsets[pos].offset = size;
27803 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT;
27804 //TODO check value source and alloc!
27805 //offsetBuffer->offsets[pos].offsetData.value.value = p->data.keyFrameData.dataSetFields;
27806 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27807 UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27808 p->data.keyFrameData.dataSetFields[i].value.data,
27809 p->data.keyFrameData.dataSetFields[i].value.type);
27810 offsetBuffer->offsets[pos].offsetData.value.value->value.storageType = UA_VARIANT_DATA_NODELETE;
27811 }
27812 size += UA_calcSizeBinary(&p->data.keyFrameData.dataSetFields[i].value, &UA_TYPES[UA_TYPES_VARIANT]);
27813 }
27814 } else if(p->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
27815 for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++){
27816 if (offsetBuffer) {
27817 size_t pos = offsetBuffer->offsetsSize;
27818 if(!increaseOffsetArray(offsetBuffer))
27819 return 0;
27820 offsetBuffer->offsets[pos].offset = size;
27821 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW;
27822 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27823 //init offset buffer with the latest value
27824 UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27825 p->data.keyFrameData.dataSetFields[i].value.data,
27826 p->data.keyFrameData.dataSetFields[i].value.type);
27827 offsetBuffer->offsets[pos].offsetData.value.value->value.storageType = UA_VARIANT_DATA_NODELETE;
27828 //count the memory size of the specific field
27829 offsetBuffer->rawMessageLength += p->data.keyFrameData.dataSetFields[i].value.type->memSize;
27830 }
27831 size += UA_calcSizeBinary(p->data.keyFrameData.dataSetFields[i].value.data,
27832 p->data.keyFrameData.dataSetFields[i].value.type);
27833 }
27834 } else if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27835 for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++) {
27836 if (offsetBuffer) {
27837 size_t pos = offsetBuffer->offsetsSize;
27838 if(!increaseOffsetArray(offsetBuffer))
27839 return 0;
27840 offsetBuffer->offsets[pos].offset = size;
27841 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE;
27842 //TODO check value source, change implementation to 'variant'
27843 offsetBuffer->offsets[pos].offsetData.value.value = p->data.keyFrameData.dataSetFields;
27844 }
27845 size += UA_calcSizeBinary(&p->data.keyFrameData.dataSetFields[i], &UA_TYPES[UA_TYPES_DATAVALUE]);
27846 }
27847 }
27848 } else if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
27849 //TODO clarify how to handle DATADELTAFRAME messages with RT
27850 if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA)
27851 size += UA_calcSizeBinary(&p->data.deltaFrameData.fieldCount, &UA_TYPES[UA_TYPES_UINT16]);
27852
27853 if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27854 for (UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) {
27855 size += UA_calcSizeBinary(&p->data.deltaFrameData.deltaFrameFields[i].fieldIndex, &UA_TYPES[UA_TYPES_UINT16]);
27856 size += UA_calcSizeBinary(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue.value, &UA_TYPES[UA_TYPES_VARIANT]);
27857 }
27858 } else if(p->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
27859 // not implemented
27860 } else if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27861 for (UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) {
27862 size += UA_calcSizeBinary(&p->data.deltaFrameData.deltaFrameFields[i].fieldIndex, &UA_TYPES[UA_TYPES_UINT16]);
27863 size += UA_calcSizeBinary(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue, &UA_TYPES[UA_TYPES_DATAVALUE]);
27864 }
27865 }
27866 }
27867 /* KeepAlive-Message contains no Payload Data */
27868 return size;
27869}
27870
27871void
27872UA_DataSetMessage_clear(const UA_DataSetMessage* p) {
27873 if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
27874 if(p->data.keyFrameData.dataSetFields != NULL) {
27875 UA_Array_delete(p->data.keyFrameData.dataSetFields,
27876 p->data.keyFrameData.fieldCount,
27877 &UA_TYPES[UA_TYPES_DATAVALUE]);
27878 }
27879
27880 /* Json keys */
27881 if(p->data.keyFrameData.fieldNames != NULL){
27882 UA_Array_delete(p->data.keyFrameData.fieldNames,
27883 p->data.keyFrameData.fieldCount,
27884 &UA_TYPES[UA_TYPES_STRING]);
27885 }
27886 } else if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
27887 if(p->data.deltaFrameData.deltaFrameFields != NULL) {
27888 for(UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) {
27889 if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27890 UA_DataValue_clear(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue);
27891 } else if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27892 UA_Variant_clear(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue.value);
27893 }
27894 }
27895 UA_free(p->data.deltaFrameData.deltaFrameFields);
27896 }
27897 }
27898}
27899
27900void
27901UA_NetworkMessageOffsetBuffer_clear(UA_NetworkMessageOffsetBuffer *ob) {
27902 UA_ByteString_clear(&ob->buffer);
27903 if(ob->nm) {
27904 UA_NetworkMessage_clear(ob->nm);
27905 UA_free(ob->nm);
27906 }
27907 ob->nm = NULL;
27908 ob->rawMessageLength = 0;
27909
27910 for(size_t i = 0; i < ob->offsetsSize; i++) {
27911 UA_NetworkMessageOffset *nmo = &ob->offsets[i];
27912 if(nmo->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT ||
27913 nmo->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW ||
27914 nmo->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE) {
27915 UA_DataValue_delete(nmo->offsetData.value.value);
27916 } else if(nmo->contentType == UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER ||
27917 nmo->contentType == UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER) {
27918 UA_DataValue_delete(nmo->offsetData.value.value);
27919 } else if(nmo->contentType == UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING) {
27920 nmo->offsetData.value.value->value.data = NULL;
27921 UA_DataValue_delete(nmo->offsetData.value.value);
27922 }
27923 }
27924
27925 UA_free(ob->offsets);
27926 ob->offsets = NULL;
27927 ob->offsetsSize = 0;
27928
27929 ob->RTsubscriberEnabled = false;
27930
27931}
27932
27933#endif /* UA_ENABLE_PUBSUB */
27934
27935/**** amalgamated original file "/src/pubsub/ua_pubsub_writer.c" ****/
27936
27937/* This Source Code Form is subject to the terms of the Mozilla Public
27938 * License, v. 2.0. If a copy of the MPL was not distributed with this
27939 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
27940 *
27941 * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
27942 * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
27943 * Copyright (c) 2019-2021 Kalycito Infotech Private Limited
27944 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
27945 * Copyright (c) 2020 Thomas Fischer, Siemens AG
27946 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
27947 */
27948
27949
27950#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
27951
27952
27953#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
27954#endif
27955
27956#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
27957#endif
27958
27959/* Forward declaration */
27960static void
27961UA_DataSetField_clear(UA_DataSetField *field);
27962
27963/**********************************************/
27964/* Connection */
27965/**********************************************/
27966
27967UA_StatusCode
27968UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src,
27969 UA_PubSubConnectionConfig *dst) {
27970 UA_StatusCode res = UA_STATUSCODE_GOOD;
27971 memcpy(dst, src, sizeof(UA_PubSubConnectionConfig));
27972 res |= UA_String_copy(&src->name, &dst->name);
27973 res |= UA_Variant_copy(&src->address, &dst->address);
27974 res |= UA_String_copy(&src->transportProfileUri, &dst->transportProfileUri);
27975 res |= UA_Variant_copy(&src->connectionTransportSettings,
27976 &dst->connectionTransportSettings);
27977 if(src->connectionPropertiesSize > 0) {
27978 dst->connectionProperties = (UA_KeyValuePair *)
27979 UA_calloc(src->connectionPropertiesSize, sizeof(UA_KeyValuePair));
27980 if(!dst->connectionProperties) {
27981 UA_PubSubConnectionConfig_clear(dst);
27982 return UA_STATUSCODE_BADOUTOFMEMORY;
27983 }
27984 for(size_t i = 0; i < src->connectionPropertiesSize; i++){
27985 res |= UA_QualifiedName_copy(&src->connectionProperties[i].key,
27986 &dst->connectionProperties[i].key);
27987 res |= UA_Variant_copy(&src->connectionProperties[i].value,
27988 &dst->connectionProperties[i].value);
27989 }
27990 }
27991 if(res != UA_STATUSCODE_GOOD)
27992 UA_PubSubConnectionConfig_clear(dst);
27993 return res;
27994}
27995
27996UA_StatusCode
27997UA_Server_getPubSubConnectionConfig(UA_Server *server, const UA_NodeId connection,
27998 UA_PubSubConnectionConfig *config) {
27999 if(!config)
28000 return UA_STATUSCODE_BADINVALIDARGUMENT;
28001 UA_PubSubConnection *currentPubSubConnection =
28002 UA_PubSubConnection_findConnectionbyId(server, connection);
28003 if(!currentPubSubConnection)
28004 return UA_STATUSCODE_BADNOTFOUND;
28005 return UA_PubSubConnectionConfig_copy(currentPubSubConnection->config, config);
28006}
28007
28008UA_PubSubConnection *
28009UA_PubSubConnection_findConnectionbyId(UA_Server *server, UA_NodeId connectionIdentifier) {
28010 UA_PubSubConnection *pubSubConnection;
28011 TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
28012 if(UA_NodeId_equal(&connectionIdentifier, &pubSubConnection->identifier))
28013 break;
28014 }
28015 return pubSubConnection;
28016}
28017
28018void
28019UA_PubSubConnectionConfig_clear(UA_PubSubConnectionConfig *connectionConfig) {
28020 UA_String_clear(&connectionConfig->name);
28021 UA_String_clear(&connectionConfig->transportProfileUri);
28022 UA_Variant_clear(&connectionConfig->connectionTransportSettings);
28023 UA_Variant_clear(&connectionConfig->address);
28024 for(size_t i = 0; i < connectionConfig->connectionPropertiesSize; i++){
28025 UA_QualifiedName_clear(&connectionConfig->connectionProperties[i].key);
28026 UA_Variant_clear(&connectionConfig->connectionProperties[i].value);
28027 }
28028 UA_free(connectionConfig->connectionProperties);
28029}
28030
28031void
28032UA_PubSubConnection_clear(UA_Server *server, UA_PubSubConnection *connection) {
28033 /* Remove WriterGroups */
28034 UA_WriterGroup *writerGroup, *tmpWriterGroup;
28035 LIST_FOREACH_SAFE(writerGroup, &connection->writerGroups, listEntry, tmpWriterGroup)
28036 UA_Server_removeWriterGroup(server, writerGroup->identifier);
28037
28038 /* Remove ReaderGroups */
28039 UA_ReaderGroup *readerGroups, *tmpReaderGroup;
28040 LIST_FOREACH_SAFE(readerGroups, &connection->readerGroups, listEntry, tmpReaderGroup)
28041 UA_Server_removeReaderGroup(server, readerGroups->identifier);
28042
28043 UA_NodeId_clear(&connection->identifier);
28044 if(connection->channel)
28045 connection->channel->close(connection->channel);
28046
28047 UA_PubSubConnectionConfig_clear(connection->config);
28048 UA_free(connection->config);
28049}
28050
28051/**********************************************/
28052/* PublishedDataSet */
28053/**********************************************/
28054
28055UA_StatusCode
28056UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src,
28057 UA_PublishedDataSetConfig *dst) {
28058 UA_StatusCode res = UA_STATUSCODE_GOOD;
28059 memcpy(dst, src, sizeof(UA_PublishedDataSetConfig));
28060 res |= UA_String_copy(&src->name, &dst->name);
28061 switch(src->publishedDataSetType) {
28062 case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
28063 //no additional items
28064 break;
28065
28066 case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
28067 if(src->config.itemsTemplate.variablesToAddSize > 0) {
28068 dst->config.itemsTemplate.variablesToAdd = (UA_PublishedVariableDataType *)
28069 UA_calloc(src->config.itemsTemplate.variablesToAddSize,
28070 sizeof(UA_PublishedVariableDataType));
28071 if(!dst->config.itemsTemplate.variablesToAdd) {
28072 res = UA_STATUSCODE_BADOUTOFMEMORY;
28073 break;
28074 }
28075 dst->config.itemsTemplate.variablesToAddSize =
28076 src->config.itemsTemplate.variablesToAddSize;
28077 }
28078
28079 for(size_t i = 0; i < src->config.itemsTemplate.variablesToAddSize; i++) {
28080 res |= UA_PublishedVariableDataType_copy(&src->config.itemsTemplate.variablesToAdd[i],
28081 &dst->config.itemsTemplate.variablesToAdd[i]);
28082 }
28083 res |= UA_DataSetMetaDataType_copy(&src->config.itemsTemplate.metaData,
28084 &dst->config.itemsTemplate.metaData);
28085 break;
28086
28087 default:
28088 res = UA_STATUSCODE_BADINVALIDARGUMENT;
28089 break;
28090 }
28091
28092 if(res != UA_STATUSCODE_GOOD)
28093 UA_PublishedDataSetConfig_clear(dst);
28094 return res;
28095}
28096
28097UA_StatusCode
28098UA_Server_getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds,
28099 UA_PublishedDataSetConfig *config) {
28100 if(!config)
28101 return UA_STATUSCODE_BADINVALIDARGUMENT;
28102 UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, pds);
28103 if(!currentPDS)
28104 return UA_STATUSCODE_BADNOTFOUND;
28105 return UA_PublishedDataSetConfig_copy(&currentPDS->config, config);
28106}
28107
28108UA_StatusCode
28109UA_Server_getPublishedDataSetMetaData(UA_Server *server, const UA_NodeId pds,
28110 UA_DataSetMetaDataType *metaData) {
28111 if(!metaData)
28112 return UA_STATUSCODE_BADINVALIDARGUMENT;
28113 UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, pds);
28114 if(!currentPDS)
28115 return UA_STATUSCODE_BADNOTFOUND;
28116 return UA_DataSetMetaDataType_copy(&currentPDS->dataSetMetaData, metaData);
28117}
28118
28119UA_PublishedDataSet *
28120UA_PublishedDataSet_findPDSbyId(UA_Server *server, UA_NodeId identifier) {
28121 UA_PublishedDataSet *tmpPDS = NULL;
28122 TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) {
28123 if(UA_NodeId_equal(&tmpPDS->identifier, &identifier))
28124 break;
28125 }
28126 return tmpPDS;
28127}
28128
28129void
28130UA_PublishedDataSetConfig_clear(UA_PublishedDataSetConfig *pdsConfig) {
28131 //delete pds config
28132 UA_String_clear(&pdsConfig->name);
28133 switch (pdsConfig->publishedDataSetType){
28134 case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
28135 //no additional items
28136 break;
28137 case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
28138 if(pdsConfig->config.itemsTemplate.variablesToAddSize > 0){
28139 for(size_t i = 0; i < pdsConfig->config.itemsTemplate.variablesToAddSize; i++){
28140 UA_PublishedVariableDataType_clear(&pdsConfig->config.itemsTemplate.variablesToAdd[i]);
28141 }
28142 UA_free(pdsConfig->config.itemsTemplate.variablesToAdd);
28143 }
28144 UA_DataSetMetaDataType_clear(&pdsConfig->config.itemsTemplate.metaData);
28145 break;
28146 default:
28147 break;
28148 }
28149}
28150
28151void
28152UA_PublishedDataSet_clear(UA_Server *server, UA_PublishedDataSet *publishedDataSet) {
28153 UA_DataSetField *field, *tmpField;
28154 TAILQ_FOREACH_SAFE(field, &publishedDataSet->fields, listEntry, tmpField) {
28155 UA_Server_removeDataSetField(server, field->identifier);
28156 }
28157 UA_PublishedDataSetConfig_clear(&publishedDataSet->config);
28158 UA_DataSetMetaDataType_clear(&publishedDataSet->dataSetMetaData);
28159 UA_NodeId_clear(&publishedDataSet->identifier);
28160}
28161
28162/* The fieldMetaData variable has to be cleaned up external in case of an error */
28163static UA_StatusCode
28164generateFieldMetaData(UA_Server *server, UA_DataSetField *field,
28165 UA_FieldMetaData *fieldMetaData) {
28166 if(field->config.dataSetFieldType != UA_PUBSUB_DATASETFIELD_VARIABLE)
28167 return UA_STATUSCODE_BADNOTSUPPORTED;
28168
28169 /* Set the field identifier */
28170 fieldMetaData->dataSetFieldId = UA_PubSubManager_generateUniqueGuid(server);
28171
28172 /* Set the description */
28173 fieldMetaData->description = UA_LOCALIZEDTEXT_ALLOC("", "");
28174
28175 /* Set the name */
28176 const UA_DataSetVariableConfig *var = &field->config.field.variable;
28177 UA_StatusCode res = UA_String_copy(&var->fieldNameAlias, &fieldMetaData->name);
28178 UA_CHECK_STATUS(res, return res);
28179
28180 /* Static value source. ToDo after freeze PR, the value source must be
28181 * checked (other behavior for static value source) */
28182 if(var->rtValueSource.rtFieldSourceEnabled &&
28183 !var->rtValueSource.rtInformationModelNode) {
28184 const UA_DataValue *svs = *var->rtValueSource.staticValueSource;
28185 if(svs->value.arrayDimensionsSize > 0) {
28186 fieldMetaData->arrayDimensions = (UA_UInt32 *)
28187 UA_calloc(svs->value.arrayDimensionsSize, sizeof(UA_UInt32));
28188 if(fieldMetaData->arrayDimensions == NULL)
28189 return UA_STATUSCODE_BADOUTOFMEMORY;
28190 memcpy(fieldMetaData->arrayDimensions, svs->value.arrayDimensions,
28191 sizeof(UA_UInt32) * svs->value.arrayDimensionsSize);
28192 }
28193 fieldMetaData->arrayDimensionsSize = svs->value.arrayDimensionsSize;
28194
28195 res = UA_NodeId_copy(&svs->value.type->typeId, &fieldMetaData->dataType);
28196 UA_CHECK_STATUS(res, return res);
28197
28198 //TODO collect value rank for the static field source
28199 fieldMetaData->properties = NULL;
28200 fieldMetaData->propertiesSize = 0;
28201 fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE;
28202 return UA_STATUSCODE_GOOD;
28203 }
28204
28205 /* Set the Array Dimensions */
28206 const UA_PublishedVariableDataType *pp = &var->publishParameters;
28207 UA_Variant value;
28208 UA_Variant_init(&value);
28209 res = UA_Server_readArrayDimensions(server, pp->publishedVariable, &value);
28210 UA_CHECK_STATUS_LOG(res, return res,
28211 WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
28212 "PubSub meta data generation. Reading the array dimensions failed.");
28213
28214 if(value.arrayDimensionsSize > 0) {
28215 fieldMetaData->arrayDimensions = (UA_UInt32 *)
28216 UA_calloc(value.arrayDimensionsSize, sizeof(UA_UInt32));
28217 if(!fieldMetaData->arrayDimensions)
28218 return UA_STATUSCODE_BADOUTOFMEMORY;
28219 memcpy(fieldMetaData->arrayDimensions, value.arrayDimensions,
28220 sizeof(UA_UInt32)*value.arrayDimensionsSize);
28221 }
28222 fieldMetaData->arrayDimensionsSize = value.arrayDimensionsSize;
28223 UA_Variant_clear(&value);
28224
28225 /* Set the DataType */
28226 res = UA_Server_readDataType(server, pp->publishedVariable,
28227 &fieldMetaData->dataType);
28228 UA_CHECK_STATUS_LOG(res, return res,
28229 WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
28230 "PubSub meta data generation. Reading the datatype failed.");
28231
28232 if(!UA_NodeId_isNull(&fieldMetaData->dataType)) {
28233 const UA_DataType *currentDataType =
28234 UA_findDataTypeWithCustom(&fieldMetaData->dataType,
28235 server->config.customDataTypes);
28236#ifdef UA_ENABLE_TYPEDESCRIPTION
28237 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
28238 "MetaData creation. Found DataType %s.", currentDataType->typeName);
28239#endif
28240 /* Check if the datatype is a builtInType, if yes set the builtinType.
28241 * TODO: Remove the magic number */
28242 if(currentDataType->typeKind <= UA_DATATYPEKIND_ENUM)
28243 fieldMetaData->builtInType = (UA_Byte)currentDataType->typeKind;
28244 } else {
28245 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28246 "PubSub meta data generation. DataType is UA_NODEID_NULL.");
28247 }
28248
28249 /* Set the ValueRank */
28250 UA_Int32 valueRank;
28251 res = UA_Server_readValueRank(server, pp->publishedVariable, &valueRank);
28252 UA_CHECK_STATUS_LOG(res, return res,
28253 WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
28254 "PubSub meta data generation. Reading the value rank failed.");
28255 fieldMetaData->valueRank = valueRank;
28256
28257 /* PromotedField? */
28258 if(var->promotedField)
28259 fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_PROMOTEDFIELD;
28260 else
28261 fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE;
28262
28263 /* Properties */
28264 fieldMetaData->properties = NULL;
28265 fieldMetaData->propertiesSize = 0;
28266
28267 //TODO collect the following fields*/
28268 //fieldMetaData.builtInType
28269 //fieldMetaData.maxStringLength
28270
28271 return UA_STATUSCODE_GOOD;
28272}
28273
28274UA_DataSetFieldResult
28275UA_Server_addDataSetField(UA_Server *server, const UA_NodeId publishedDataSet,
28276 const UA_DataSetFieldConfig *fieldConfig,
28277 UA_NodeId *fieldIdentifier) {
28278 UA_DataSetFieldResult result = {0};
28279 if(!fieldConfig) {
28280 result.result = UA_STATUSCODE_BADINVALIDARGUMENT;
28281 return result;
28282 }
28283
28284 UA_PublishedDataSet *currDS =
28285 UA_PublishedDataSet_findPDSbyId(server, publishedDataSet);
28286 if(!currDS) {
28287 result.result = UA_STATUSCODE_BADNOTFOUND;
28288 return result;
28289 }
28290
28291 if(currDS->configurationFrozen) {
28292 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28293 "Adding DataSetField failed. PublishedDataSet is frozen.");
28294 result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
28295 return result;
28296 }
28297
28298 if(currDS->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS) {
28299 result.result = UA_STATUSCODE_BADNOTIMPLEMENTED;
28300 return result;
28301 }
28302
28303 UA_DataSetField *newField = (UA_DataSetField*)UA_calloc(1, sizeof(UA_DataSetField));
28304 if(!newField) {
28305 result.result = UA_STATUSCODE_BADINTERNALERROR;
28306 return result;
28307 }
28308
28309 UA_StatusCode retVal = UA_DataSetFieldConfig_copy(fieldConfig, &newField->config);
28310 if(retVal != UA_STATUSCODE_GOOD) {
28311 UA_free(newField);
28312 result.result = retVal;
28313 return result;
28314 }
28315
28316 newField->publishedDataSet = currDS->identifier;
28317
28318 /* Initialize the field metadata. Also generates a FieldId */
28319 UA_FieldMetaData fmd;
28320 UA_FieldMetaData_init(&fmd);
28321 result.result = generateFieldMetaData(server, newField, &fmd);
28322 if(result.result != UA_STATUSCODE_GOOD) {
28323 UA_FieldMetaData_clear(&fmd);
28324 UA_DataSetFieldConfig_clear(&newField->config);
28325 UA_free(newField);
28326 return result;
28327 }
28328
28329 /* Append to the metadata fields array. Point of last return. */
28330 result.result = UA_Array_append((void**)&currDS->dataSetMetaData.fields,
28331 &currDS->dataSetMetaData.fieldsSize,
28332 &fmd, &UA_TYPES[UA_TYPES_FIELDMETADATA]);
28333 if(result.result != UA_STATUSCODE_GOOD) {
28334 UA_FieldMetaData_clear(&fmd);
28335 UA_DataSetFieldConfig_clear(&newField->config);
28336 UA_free(newField);
28337 return result;
28338 }
28339
28340 /* Copy the identifier from the metadata. Cannot fail with a guid NodeId. */
28341 newField->identifier = UA_NODEID_GUID(1, fmd.dataSetFieldId);
28342 if(fieldIdentifier)
28343 UA_NodeId_copy(&newField->identifier, fieldIdentifier);
28344
28345 /* Register the field. The order of DataSetFields should be the same in both
28346 * creating and publishing. So adding DataSetFields at the the end of the
28347 * DataSets using the TAILQ structure. */
28348 TAILQ_INSERT_TAIL(&currDS->fields, newField, listEntry);
28349 currDS->fieldSize++;
28350
28351 if(newField->config.field.variable.promotedField)
28352 currDS->promotedFieldsCount++;
28353
28354 /* The values of the metadata are "borrowed" in a mirrored structure in the
28355 * pds. Reset them after resizing the array. */
28356 size_t counter = 0;
28357 UA_DataSetField *dsf;
28358 TAILQ_FOREACH(dsf, &currDS->fields, listEntry) {
28359 dsf->fieldMetaData = currDS->dataSetMetaData.fields[counter++];
28360 }
28361
28362 /* Update major version of parent published data set */
28363 currDS->dataSetMetaData.configurationVersion.majorVersion =
28364 UA_PubSubConfigurationVersionTimeDifference();
28365
28366 result.configurationVersion.majorVersion =
28367 currDS->dataSetMetaData.configurationVersion.majorVersion;
28368 result.configurationVersion.minorVersion =
28369 currDS->dataSetMetaData.configurationVersion.minorVersion;
28370 return result;
28371}
28372
28373UA_DataSetFieldResult
28374UA_Server_removeDataSetField(UA_Server *server, const UA_NodeId dsf) {
28375 UA_DataSetFieldResult result = {0};
28376
28377 UA_DataSetField *currentField = UA_DataSetField_findDSFbyId(server, dsf);
28378 if(!currentField) {
28379 result.result = UA_STATUSCODE_BADNOTFOUND;
28380 return result;
28381 }
28382
28383 if(currentField->configurationFrozen) {
28384 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28385 "Remove DataSetField failed. DataSetField is frozen.");
28386 result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
28387 return result;
28388 }
28389
28390 UA_PublishedDataSet *pds =
28391 UA_PublishedDataSet_findPDSbyId(server, currentField->publishedDataSet);
28392 if(!pds) {
28393 result.result = UA_STATUSCODE_BADNOTFOUND;
28394 return result;
28395 }
28396
28397 if(pds->configurationFrozen) {
28398 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28399 "Remove DataSetField failed. PublishedDataSet is frozen.");
28400 result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
28401 return result;
28402 }
28403
28404 /* Reduce the counters before the config is cleaned up */
28405 if(currentField->config.field.variable.promotedField)
28406 pds->promotedFieldsCount--;
28407 pds->fieldSize--;
28408
28409 /* Update major version of PublishedDataSet */
28410 pds->dataSetMetaData.configurationVersion.majorVersion =
28411 UA_PubSubConfigurationVersionTimeDifference();
28412
28413 /* Clean up */
28414 currentField->fieldMetaData.arrayDimensions = NULL;
28415 currentField->fieldMetaData.properties = NULL;
28416 currentField->fieldMetaData.name = UA_STRING_NULL;
28417 currentField->fieldMetaData.description.locale = UA_STRING_NULL;
28418 currentField->fieldMetaData.description.text = UA_STRING_NULL;
28419 UA_DataSetField_clear(currentField);
28420
28421 /* Remove */
28422 TAILQ_REMOVE(&pds->fields, currentField, listEntry);
28423 UA_free(currentField);
28424
28425 /* Regenerate DataSetMetaData */
28426 pds->dataSetMetaData.fieldsSize--;
28427 if(pds->dataSetMetaData.fieldsSize > 0) {
28428 for(size_t i = 0; i < pds->dataSetMetaData.fieldsSize+1; i++) {
28429 UA_FieldMetaData_clear(&pds->dataSetMetaData.fields[i]);
28430 }
28431 UA_free(pds->dataSetMetaData.fields);
28432 UA_FieldMetaData *fieldMetaData = (UA_FieldMetaData *)
28433 UA_calloc(pds->dataSetMetaData.fieldsSize, sizeof(UA_FieldMetaData));
28434 if(!fieldMetaData) {
28435 result.result = UA_STATUSCODE_BADOUTOFMEMORY;
28436 return result;
28437 }
28438 UA_DataSetField *tmpDSF;
28439 size_t counter = 0;
28440 TAILQ_FOREACH(tmpDSF, &pds->fields, listEntry){
28441 result.result = generateFieldMetaData(server, tmpDSF, &fieldMetaData[counter]);
28442 if(result.result != UA_STATUSCODE_GOOD) {
28443 UA_FieldMetaData_clear(&fieldMetaData[counter]);
28444 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28445 "PubSub MetaData generation failed!");
28446 break;
28447 }
28448 counter++;
28449 }
28450 pds->dataSetMetaData.fields = fieldMetaData;
28451 } else {
28452 UA_FieldMetaData_delete(pds->dataSetMetaData.fields);
28453 pds->dataSetMetaData.fields = NULL;
28454 }
28455
28456 result.configurationVersion.majorVersion =
28457 pds->dataSetMetaData.configurationVersion.majorVersion;
28458 result.configurationVersion.minorVersion =
28459 pds->dataSetMetaData.configurationVersion.minorVersion;
28460 return result;
28461}
28462
28463/**********************************************/
28464/* DataSetWriter */
28465/**********************************************/
28466
28467UA_StatusCode
28468UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src,
28469 UA_DataSetWriterConfig *dst){
28470 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
28471 memcpy(dst, src, sizeof(UA_DataSetWriterConfig));
28472 retVal |= UA_String_copy(&src->name, &dst->name);
28473 retVal |= UA_String_copy(&src->dataSetName, &dst->dataSetName);
28474 retVal |= UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
28475 if(src->dataSetWriterPropertiesSize > 0) {
28476 dst->dataSetWriterProperties = (UA_KeyValuePair *)
28477 UA_calloc(src->dataSetWriterPropertiesSize, sizeof(UA_KeyValuePair));
28478 if(!dst->dataSetWriterProperties)
28479 return UA_STATUSCODE_BADOUTOFMEMORY;
28480 for(size_t i = 0; i < src->dataSetWriterPropertiesSize; i++){
28481 retVal |= UA_KeyValuePair_copy(&src->dataSetWriterProperties[i],
28482 &dst->dataSetWriterProperties[i]);
28483 }
28484 }
28485 return retVal;
28486}
28487
28488UA_StatusCode
28489UA_Server_getDataSetWriterConfig(UA_Server *server, const UA_NodeId dsw,
28490 UA_DataSetWriterConfig *config) {
28491 if(!config)
28492 return UA_STATUSCODE_BADINVALIDARGUMENT;
28493 UA_DataSetWriter *currentDataSetWriter = UA_DataSetWriter_findDSWbyId(server, dsw);
28494 if(!currentDataSetWriter)
28495 return UA_STATUSCODE_BADNOTFOUND;
28496 return UA_DataSetWriterConfig_copy(&currentDataSetWriter->config, config);
28497}
28498
28499UA_StatusCode
28500UA_Server_DataSetWriter_getState(UA_Server *server, UA_NodeId dataSetWriterIdentifier,
28501 UA_PubSubState *state) {
28502 if((server == NULL) || (state == NULL))
28503 return UA_STATUSCODE_BADINVALIDARGUMENT;
28504 UA_DataSetWriter *currentDataSetWriter =
28505 UA_DataSetWriter_findDSWbyId(server, dataSetWriterIdentifier);
28506 if(currentDataSetWriter == NULL)
28507 return UA_STATUSCODE_BADNOTFOUND;
28508 *state = currentDataSetWriter->state;
28509 return UA_STATUSCODE_GOOD;
28510}
28511
28512UA_DataSetWriter *
28513UA_DataSetWriter_findDSWbyId(UA_Server *server, UA_NodeId identifier) {
28514 UA_PubSubConnection *pubSubConnection;
28515 TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
28516 UA_WriterGroup *tmpWriterGroup;
28517 LIST_FOREACH(tmpWriterGroup, &pubSubConnection->writerGroups, listEntry){
28518 UA_DataSetWriter *tmpWriter;
28519 LIST_FOREACH(tmpWriter, &tmpWriterGroup->writers, listEntry){
28520 if(UA_NodeId_equal(&tmpWriter->identifier, &identifier)){
28521 return tmpWriter;
28522 }
28523 }
28524 }
28525 }
28526 return NULL;
28527}
28528
28529void
28530UA_DataSetWriterConfig_clear(UA_DataSetWriterConfig *pdsConfig) {
28531 UA_String_clear(&pdsConfig->name);
28532 UA_String_clear(&pdsConfig->dataSetName);
28533 for(size_t i = 0; i < pdsConfig->dataSetWriterPropertiesSize; i++) {
28534 UA_KeyValuePair_clear(&pdsConfig->dataSetWriterProperties[i]);
28535 }
28536 UA_free(pdsConfig->dataSetWriterProperties);
28537 UA_ExtensionObject_clear(&pdsConfig->messageSettings);
28538}
28539
28540static void
28541UA_DataSetWriter_clear(UA_Server *server, UA_DataSetWriter *dataSetWriter) {
28542 UA_DataSetWriterConfig_clear(&dataSetWriter->config);
28543 UA_NodeId_clear(&dataSetWriter->identifier);
28544 UA_NodeId_clear(&dataSetWriter->linkedWriterGroup);
28545 UA_NodeId_clear(&dataSetWriter->connectedDataSet);
28546
28547 /* Delete lastSamples store */
28548#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
28549 for(size_t i = 0; i < dataSetWriter->lastSamplesCount; i++) {
28550 UA_DataValue_clear(&dataSetWriter->lastSamples[i].value);
28551 }
28552 UA_free(dataSetWriter->lastSamples);
28553 dataSetWriter->lastSamples = NULL;
28554 dataSetWriter->lastSamplesCount = 0;
28555#endif
28556}
28557
28558//state machine methods not part of the open62541 state machine API
28559UA_StatusCode
28560UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state,
28561 UA_DataSetWriter *dataSetWriter) {
28562 switch(state){
28563 case UA_PUBSUBSTATE_DISABLED:
28564 switch (dataSetWriter->state){
28565 case UA_PUBSUBSTATE_DISABLED:
28566 return UA_STATUSCODE_GOOD;
28567 case UA_PUBSUBSTATE_PAUSED:
28568 dataSetWriter->state = UA_PUBSUBSTATE_DISABLED;
28569 //no further action is required
28570 break;
28571 case UA_PUBSUBSTATE_OPERATIONAL:
28572 dataSetWriter->state = UA_PUBSUBSTATE_DISABLED;
28573 break;
28574 case UA_PUBSUBSTATE_ERROR:
28575 break;
28576 default:
28577 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28578 "Received unknown PubSub state!");
28579 }
28580 break;
28581 case UA_PUBSUBSTATE_PAUSED:
28582 switch (dataSetWriter->state){
28583 case UA_PUBSUBSTATE_DISABLED:
28584 break;
28585 case UA_PUBSUBSTATE_PAUSED:
28586 return UA_STATUSCODE_GOOD;
28587 case UA_PUBSUBSTATE_OPERATIONAL:
28588 break;
28589 case UA_PUBSUBSTATE_ERROR:
28590 break;
28591 default:
28592 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28593 "Received unknown PubSub state!");
28594 }
28595 break;
28596 case UA_PUBSUBSTATE_OPERATIONAL:
28597 switch (dataSetWriter->state){
28598 case UA_PUBSUBSTATE_DISABLED:
28599 dataSetWriter->state = UA_PUBSUBSTATE_OPERATIONAL;
28600 break;
28601 case UA_PUBSUBSTATE_PAUSED:
28602 break;
28603 case UA_PUBSUBSTATE_OPERATIONAL:
28604 return UA_STATUSCODE_GOOD;
28605 case UA_PUBSUBSTATE_ERROR:
28606 break;
28607 default:
28608 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28609 "Received unknown PubSub state!");
28610 }
28611 break;
28612 case UA_PUBSUBSTATE_ERROR:
28613 switch (dataSetWriter->state){
28614 case UA_PUBSUBSTATE_DISABLED:
28615 break;
28616 case UA_PUBSUBSTATE_PAUSED:
28617 break;
28618 case UA_PUBSUBSTATE_OPERATIONAL:
28619 break;
28620 case UA_PUBSUBSTATE_ERROR:
28621 return UA_STATUSCODE_GOOD;
28622 default:
28623 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28624 "Received unknown PubSub state!");
28625 }
28626 break;
28627 default:
28628 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28629 "Received unknown PubSub state!");
28630 }
28631 return UA_STATUSCODE_GOOD;
28632}
28633
28634UA_StatusCode
28635UA_Server_addDataSetWriter(UA_Server *server,
28636 const UA_NodeId writerGroup, const UA_NodeId dataSet,
28637 const UA_DataSetWriterConfig *dataSetWriterConfig,
28638 UA_NodeId *writerIdentifier) {
28639 if(!dataSetWriterConfig)
28640 return UA_STATUSCODE_BADINVALIDARGUMENT;
28641
28642 UA_PublishedDataSet *currentDataSetContext =
28643 UA_PublishedDataSet_findPDSbyId(server, dataSet);
28644 if(!currentDataSetContext)
28645 return UA_STATUSCODE_BADNOTFOUND;
28646
28647 if(currentDataSetContext->configurationFrozen){
28648 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28649 "Adding DataSetWriter failed. PublishedDataSet is frozen.");
28650 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28651 }
28652
28653 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
28654 if(!wg)
28655 return UA_STATUSCODE_BADNOTFOUND;
28656
28657 if(wg->configurationFrozen) {
28658 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28659 "Adding DataSetWriter failed. WriterGroup is frozen.");
28660 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28661 }
28662
28663 if(wg->config.rtLevel != UA_PUBSUB_RT_NONE) {
28664 UA_DataSetField *tmpDSF;
28665 TAILQ_FOREACH(tmpDSF, &currentDataSetContext->fields, listEntry) {
28666 if(!tmpDSF->config.field.variable.rtValueSource.rtFieldSourceEnabled &&
28667 !tmpDSF->config.field.variable.rtValueSource.rtInformationModelNode) {
28668 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28669 "Adding DataSetWriter failed. Fields in PDS are not RT capable.");
28670 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28671 }
28672 }
28673 }
28674
28675 UA_DataSetWriter *newDataSetWriter = (UA_DataSetWriter *)
28676 UA_calloc(1, sizeof(UA_DataSetWriter));
28677 if(!newDataSetWriter)
28678 return UA_STATUSCODE_BADOUTOFMEMORY;
28679
28680 newDataSetWriter->componentType = UA_PUBSUB_COMPONENT_DATASETWRITER;
28681
28682 UA_StatusCode res = UA_STATUSCODE_GOOD;
28683 if(wg->state == UA_PUBSUBSTATE_OPERATIONAL) {
28684 res = UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL,
28685 newDataSetWriter);
28686 if(res != UA_STATUSCODE_GOOD) {
28687 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
28688 "Add DataSetWriter failed. setPubSubState failed.");
28689 UA_free(newDataSetWriter);
28690 return res;
28691 }
28692 }
28693
28694 /* Copy the config into the new dataSetWriter */
28695 res = UA_DataSetWriterConfig_copy(dataSetWriterConfig, &newDataSetWriter->config);
28696 UA_CHECK_STATUS(res, UA_free(newDataSetWriter); return res);
28697
28698 /* Save the current version of the connected PublishedDataSet */
28699 newDataSetWriter->connectedDataSetVersion =
28700 currentDataSetContext->dataSetMetaData.configurationVersion;
28701
28702#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
28703 /* Initialize the queue for the last values */
28704 if(currentDataSetContext->fieldSize > 0) {
28705 newDataSetWriter->lastSamples = (UA_DataSetWriterSample*)
28706 UA_calloc(currentDataSetContext->fieldSize, sizeof(UA_DataSetWriterSample));
28707 if(!newDataSetWriter->lastSamples) {
28708 UA_DataSetWriterConfig_clear(&newDataSetWriter->config);
28709 UA_free(newDataSetWriter);
28710 return UA_STATUSCODE_BADOUTOFMEMORY;
28711 }
28712 newDataSetWriter->lastSamplesCount = currentDataSetContext->fieldSize;
28713 for(size_t i = 0; i < newDataSetWriter->lastSamplesCount; i++) {
28714 UA_DataValue_init(&newDataSetWriter->lastSamples[i].value);
28715 newDataSetWriter->lastSamples[i].valueChanged = false;
28716 }
28717 }
28718#endif
28719
28720 /* Connect PublishedDataSet with DataSetWriter */
28721 newDataSetWriter->connectedDataSet = currentDataSetContext->identifier;
28722 newDataSetWriter->linkedWriterGroup = wg->identifier;
28723
28724 /* Add the new writer to the group */
28725 LIST_INSERT_HEAD(&wg->writers, newDataSetWriter, listEntry);
28726 wg->writersCount++;
28727
28728#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
28729 res |= addDataSetWriterRepresentation(server, newDataSetWriter);
28730#else
28731 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
28732 &newDataSetWriter->identifier);
28733#endif
28734 if(writerIdentifier)
28735 UA_NodeId_copy(&newDataSetWriter->identifier, writerIdentifier);
28736 return res;
28737}
28738
28739UA_StatusCode
28740UA_DataSetWriter_remove(UA_Server *server, UA_WriterGroup *linkedWriterGroup,
28741 UA_DataSetWriter *dataSetWriter) {
28742 /* Frozen? */
28743 if(linkedWriterGroup->configurationFrozen) {
28744 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28745 "Remove DataSetWriter failed. WriterGroup is frozen.");
28746 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28747 }
28748
28749 /* Remove from information model */
28750#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
28751 removeDataSetWriterRepresentation(server, dataSetWriter);
28752#endif
28753
28754 /* Remove DataSetWriter from group */
28755 UA_DataSetWriter_clear(server, dataSetWriter);
28756 LIST_REMOVE(dataSetWriter, listEntry);
28757 linkedWriterGroup->writersCount--;
28758 UA_free(dataSetWriter);
28759 return UA_STATUSCODE_GOOD;
28760}
28761
28762UA_StatusCode
28763UA_Server_removeDataSetWriter(UA_Server *server, const UA_NodeId dsw) {
28764 UA_DataSetWriter *dataSetWriter = UA_DataSetWriter_findDSWbyId(server, dsw);
28765 if(!dataSetWriter)
28766 return UA_STATUSCODE_BADNOTFOUND;
28767
28768 if(dataSetWriter->configurationFrozen) {
28769 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28770 "Remove DataSetWriter failed. DataSetWriter is frozen.");
28771 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28772 }
28773
28774 UA_WriterGroup *linkedWriterGroup =
28775 UA_WriterGroup_findWGbyId(server, dataSetWriter->linkedWriterGroup);
28776 if(!linkedWriterGroup)
28777 return UA_STATUSCODE_BADNOTFOUND;
28778
28779 return UA_DataSetWriter_remove(server, linkedWriterGroup, dataSetWriter);
28780}
28781
28782/**********************************************/
28783/* DataSetField */
28784/**********************************************/
28785
28786static void
28787UA_DataSetField_clear(UA_DataSetField *field) {
28788 UA_DataSetFieldConfig_clear(&field->config);
28789 UA_NodeId_clear(&field->identifier);
28790 UA_NodeId_clear(&field->publishedDataSet);
28791 UA_FieldMetaData_clear(&field->fieldMetaData);
28792}
28793
28794UA_StatusCode
28795UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src,
28796 UA_DataSetFieldConfig *dst) {
28797 if(src->dataSetFieldType != UA_PUBSUB_DATASETFIELD_VARIABLE)
28798 return UA_STATUSCODE_BADNOTSUPPORTED;
28799 memcpy(dst, src, sizeof(UA_DataSetFieldConfig));
28800 UA_StatusCode res = UA_STATUSCODE_GOOD;
28801 res |= UA_String_copy(&src->field.variable.fieldNameAlias,
28802 &dst->field.variable.fieldNameAlias);
28803 res |= UA_PublishedVariableDataType_copy(&src->field.variable.publishParameters,
28804 &dst->field.variable.publishParameters);
28805 if(res != UA_STATUSCODE_GOOD)
28806 UA_DataSetFieldConfig_clear(dst);
28807 return res;
28808}
28809
28810UA_StatusCode
28811UA_Server_getDataSetFieldConfig(UA_Server *server, const UA_NodeId dsf,
28812 UA_DataSetFieldConfig *config) {
28813 if(!config)
28814 return UA_STATUSCODE_BADINVALIDARGUMENT;
28815 UA_DataSetField *currentDataSetField = UA_DataSetField_findDSFbyId(server, dsf);
28816 if(!currentDataSetField)
28817 return UA_STATUSCODE_BADNOTFOUND;
28818 return UA_DataSetFieldConfig_copy(&currentDataSetField->config, config);
28819}
28820
28821UA_DataSetField *
28822UA_DataSetField_findDSFbyId(UA_Server *server, UA_NodeId identifier) {
28823 UA_PublishedDataSet *tmpPDS;
28824 TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) {
28825 UA_DataSetField *tmpField;
28826 TAILQ_FOREACH(tmpField, &tmpPDS->fields, listEntry) {
28827 if(UA_NodeId_equal(&tmpField->identifier, &identifier))
28828 return tmpField;
28829 }
28830 }
28831 return NULL;
28832}
28833
28834void
28835UA_DataSetFieldConfig_clear(UA_DataSetFieldConfig *dataSetFieldConfig) {
28836 if(dataSetFieldConfig->dataSetFieldType == UA_PUBSUB_DATASETFIELD_VARIABLE) {
28837 UA_String_clear(&dataSetFieldConfig->field.variable.fieldNameAlias);
28838 UA_PublishedVariableDataType_clear(&dataSetFieldConfig->field.variable.publishParameters);
28839 }
28840}
28841
28842/*********************************************************/
28843/* PublishValues handling */
28844/*********************************************************/
28845
28846/* Compare two variants. Internally used for value change detection. */
28847#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
28848static UA_Boolean
28849valueChangedVariant(UA_Variant *oldValue, UA_Variant *newValue) {
28850 if(!oldValue || !newValue)
28851 return false;
28852
28853 size_t oldValueEncodingSize = UA_calcSizeBinary(oldValue, &UA_TYPES[UA_TYPES_VARIANT]);
28854 size_t newValueEncodingSize = UA_calcSizeBinary(newValue, &UA_TYPES[UA_TYPES_VARIANT]);
28855 if(oldValueEncodingSize == 0 || newValueEncodingSize == 0)
28856 return false;
28857
28858 if(oldValueEncodingSize != newValueEncodingSize)
28859 return true;
28860
28861 UA_ByteString oldValueEncoding = {0};
28862 UA_StatusCode res = UA_ByteString_allocBuffer(&oldValueEncoding, oldValueEncodingSize);
28863 if(res != UA_STATUSCODE_GOOD)
28864 return false;
28865
28866 UA_ByteString newValueEncoding = {0};
28867 res = UA_ByteString_allocBuffer(&newValueEncoding, newValueEncodingSize);
28868 if(res != UA_STATUSCODE_GOOD) {
28869 UA_ByteString_clear(&oldValueEncoding);
28870 return false;
28871 }
28872
28873 UA_Byte *bufPosOldValue = oldValueEncoding.data;
28874 const UA_Byte *bufEndOldValue = &oldValueEncoding.data[oldValueEncoding.length];
28875 UA_Byte *bufPosNewValue = newValueEncoding.data;
28876 const UA_Byte *bufEndNewValue = &newValueEncoding.data[newValueEncoding.length];
28877
28878 UA_Boolean compareResult = false; /* default */
28879
28880 res = UA_encodeBinaryInternal(oldValue, &UA_TYPES[UA_TYPES_VARIANT],
28881 &bufPosOldValue, &bufEndOldValue, NULL, NULL);
28882 if(res != UA_STATUSCODE_GOOD)
28883 goto cleanup;
28884
28885 res = UA_encodeBinaryInternal(newValue, &UA_TYPES[UA_TYPES_VARIANT],
28886 &bufPosNewValue, &bufEndNewValue, NULL, NULL);
28887 if(res != UA_STATUSCODE_GOOD)
28888 goto cleanup;
28889
28890 oldValueEncoding.length = (uintptr_t)bufPosOldValue - (uintptr_t)oldValueEncoding.data;
28891 newValueEncoding.length = (uintptr_t)bufPosNewValue - (uintptr_t)newValueEncoding.data;
28892 compareResult = !UA_ByteString_equal(&oldValueEncoding, &newValueEncoding);
28893
28894 cleanup:
28895 UA_ByteString_clear(&oldValueEncoding);
28896 UA_ByteString_clear(&newValueEncoding);
28897 return compareResult;
28898}
28899#endif
28900
28901/* Obtain the latest value for a specific DataSetField. This method is currently
28902 * called inside the DataSetMessage generation process. */
28903static void
28904UA_PubSubDataSetField_sampleValue(UA_Server *server, UA_DataSetField *field,
28905 UA_DataValue *value) {
28906 UA_PublishedVariableDataType *params = &field->config.field.variable.publishParameters;
28907
28908 /* Read the value */
28909 if(field->config.field.variable.rtValueSource.rtInformationModelNode) {
28910 const UA_VariableNode *rtNode = (const UA_VariableNode *)
28911 UA_NODESTORE_GET(server, &params->publishedVariable);
28912 *value = **rtNode->valueBackend.backend.external.value;
28913 value->value.storageType = UA_VARIANT_DATA_NODELETE;
28914 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
28915 } else if(field->config.field.variable.rtValueSource.rtFieldSourceEnabled == UA_FALSE){
28916 UA_ReadValueId rvid;
28917 UA_ReadValueId_init(&rvid);
28918 rvid.nodeId = params->publishedVariable;
28919 rvid.attributeId = params->attributeId;
28920 rvid.indexRange = params->indexRange;
28921 *value = UA_Server_read(server, &rvid, UA_TIMESTAMPSTORETURN_BOTH);
28922 } else {
28923 *value = **field->config.field.variable.rtValueSource.staticValueSource;
28924 value->value.storageType = UA_VARIANT_DATA_NODELETE;
28925 }
28926}
28927
28928static UA_StatusCode
28929UA_PubSubDataSetWriter_generateKeyFrameMessage(UA_Server *server,
28930 UA_DataSetMessage *dataSetMessage,
28931 UA_DataSetWriter *dataSetWriter) {
28932 UA_PublishedDataSet *currentDataSet =
28933 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
28934 if(!currentDataSet)
28935 return UA_STATUSCODE_BADNOTFOUND;
28936
28937 /* Prepare DataSetMessageContent */
28938 dataSetMessage->header.dataSetMessageValid = true;
28939 dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
28940 dataSetMessage->data.keyFrameData.fieldCount = currentDataSet->fieldSize;
28941 dataSetMessage->data.keyFrameData.dataSetFields = (UA_DataValue *)
28942 UA_Array_new(currentDataSet->fieldSize, &UA_TYPES[UA_TYPES_DATAVALUE]);
28943 if(!dataSetMessage->data.keyFrameData.dataSetFields)
28944 return UA_STATUSCODE_BADOUTOFMEMORY;
28945
28946#ifdef UA_ENABLE_JSON_ENCODING
28947 dataSetMessage->data.keyFrameData.fieldNames = (UA_String *)
28948 UA_Array_new(currentDataSet->fieldSize, &UA_TYPES[UA_TYPES_STRING]);
28949 if(!dataSetMessage->data.keyFrameData.fieldNames) {
28950 UA_DataSetMessage_clear(dataSetMessage);
28951 return UA_STATUSCODE_BADOUTOFMEMORY;
28952 }
28953#endif
28954
28955 /* Loop over the fields */
28956 size_t counter = 0;
28957 UA_DataSetField *dsf;
28958 TAILQ_FOREACH(dsf, &currentDataSet->fields, listEntry) {
28959#ifdef UA_ENABLE_JSON_ENCODING
28960 /* Set the field name alias */
28961 UA_String_copy(&dsf->config.field.variable.fieldNameAlias,
28962 &dataSetMessage->data.keyFrameData.fieldNames[counter]);
28963#endif
28964
28965 /* Sample the value */
28966 UA_DataValue *dfv = &dataSetMessage->data.keyFrameData.dataSetFields[counter];
28967 UA_PubSubDataSetField_sampleValue(server, dsf, dfv);
28968
28969 /* Deactivate statuscode? */
28970 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
28971 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0)
28972 dfv->hasStatus = false;
28973
28974 /* Deactivate timestamps */
28975 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
28976 (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0)
28977 dfv->hasSourceTimestamp = false;
28978 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
28979 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0)
28980 dfv->hasSourcePicoseconds = false;
28981 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
28982 (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0)
28983 dfv->hasServerTimestamp = false;
28984 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
28985 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0)
28986 dfv->hasServerPicoseconds = false;
28987
28988#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
28989 /* Update lastValue store */
28990 UA_DataValue_clear(&dataSetWriter->lastSamples[counter].value);
28991 UA_DataValue_copy(dfv, &dataSetWriter->lastSamples[counter].value);
28992#endif
28993
28994 counter++;
28995 }
28996 return UA_STATUSCODE_GOOD;
28997}
28998
28999#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
29000static UA_StatusCode
29001UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_Server *server,
29002 UA_DataSetMessage *dataSetMessage,
29003 UA_DataSetWriter *dataSetWriter) {
29004 UA_PublishedDataSet *currentDataSet =
29005 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
29006 if(!currentDataSet)
29007 return UA_STATUSCODE_BADNOTFOUND;
29008
29009 /* Prepare DataSetMessageContent */
29010 memset(dataSetMessage, 0, sizeof(UA_DataSetMessage));
29011 dataSetMessage->header.dataSetMessageValid = true;
29012 dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATADELTAFRAME;
29013 if(currentDataSet->fieldSize == 0)
29014 return UA_STATUSCODE_GOOD;
29015
29016 UA_DataSetField *dsf;
29017 size_t counter = 0;
29018 TAILQ_FOREACH(dsf, &currentDataSet->fields, listEntry) {
29019 /* Sample the value */
29020 UA_DataValue value;
29021 UA_DataValue_init(&value);
29022 UA_PubSubDataSetField_sampleValue(server, dsf, &value);
29023
29024 /* Check if the value has changed */
29025 UA_DataSetWriterSample *ls = &dataSetWriter->lastSamples[counter];
29026 if(valueChangedVariant(&ls->value.value, &value.value)) {
29027 /* increase fieldCount for current delta message */
29028 dataSetMessage->data.deltaFrameData.fieldCount++;
29029 ls->valueChanged = true;
29030
29031 /* Update last stored sample */
29032 UA_DataValue_clear(&ls->value);
29033 ls->value = value;
29034 } else {
29035 UA_DataValue_clear(&value);
29036 ls->valueChanged = false;
29037 }
29038
29039 counter++;
29040 }
29041
29042 /* Allocate DeltaFrameFields */
29043 UA_DataSetMessage_DeltaFrameField *deltaFields = (UA_DataSetMessage_DeltaFrameField *)
29044 UA_calloc(dataSetMessage->data.deltaFrameData.fieldCount,
29045 sizeof(UA_DataSetMessage_DeltaFrameField));
29046 if(!deltaFields)
29047 return UA_STATUSCODE_BADOUTOFMEMORY;
29048
29049 dataSetMessage->data.deltaFrameData.deltaFrameFields = deltaFields;
29050 size_t currentDeltaField = 0;
29051 for(size_t i = 0; i < currentDataSet->fieldSize; i++) {
29052 if(!dataSetWriter->lastSamples[i].valueChanged)
29053 continue;
29054
29055 UA_DataSetMessage_DeltaFrameField *dff = &deltaFields[currentDeltaField];
29056
29057 dff->fieldIndex = (UA_UInt16) i;
29058 UA_DataValue_copy(&dataSetWriter->lastSamples[i].value, &dff->fieldValue);
29059 dataSetWriter->lastSamples[i].valueChanged = false;
29060
29061 /* Deactivate statuscode? */
29062 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29063 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0)
29064 dff->fieldValue.hasStatus = false;
29065
29066 /* Deactivate timestamps? */
29067 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29068 (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0)
29069 dff->fieldValue.hasSourceTimestamp = false;
29070 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29071 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0)
29072 dff->fieldValue.hasServerPicoseconds = false;
29073 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29074 (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0)
29075 dff->fieldValue.hasServerTimestamp = false;
29076 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29077 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0)
29078 dff->fieldValue.hasServerPicoseconds = false;
29079
29080 currentDeltaField++;
29081 }
29082 return UA_STATUSCODE_GOOD;
29083}
29084#endif
29085
29086/* Generate a DataSetMessage for the given writer. */
29087UA_StatusCode
29088UA_DataSetWriter_generateDataSetMessage(UA_Server *server,
29089 UA_DataSetMessage *dataSetMessage,
29090 UA_DataSetWriter *dataSetWriter) {
29091 UA_PublishedDataSet *currentDataSet =
29092 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
29093 if(!currentDataSet)
29094 return UA_STATUSCODE_BADNOTFOUND;
29095
29096 /* Reset the message */
29097 memset(dataSetMessage, 0, sizeof(UA_DataSetMessage));
29098
29099 /* The configuration Flags are included
29100 * inside the std. defined UA_UadpDataSetWriterMessageDataType */
29101 UA_UadpDataSetWriterMessageDataType defaultUadpConfiguration;
29102 UA_UadpDataSetWriterMessageDataType *dsm = NULL;
29103 UA_JsonDataSetWriterMessageDataType *jsonDsm = NULL;
29104 const UA_ExtensionObject *ms = &dataSetWriter->config.messageSettings;
29105 if((ms->encoding == UA_EXTENSIONOBJECT_DECODED ||
29106 ms->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
29107 ms->content.decoded.type == &UA_TYPES[UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE]) {
29108 dsm = (UA_UadpDataSetWriterMessageDataType*)ms->content.decoded.data; /* type is UADP */
29109 } else if((ms->encoding == UA_EXTENSIONOBJECT_DECODED ||
29110 ms->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
29111 ms->content.decoded.type == &UA_TYPES[UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE]) {
29112 jsonDsm = (UA_JsonDataSetWriterMessageDataType*)ms->content.decoded.data; /* type is JSON */
29113 } else {
29114 /* Create default flag configuration if no
29115 * UadpDataSetWriterMessageDataType was passed in */
29116 memset(&defaultUadpConfiguration, 0, sizeof(UA_UadpDataSetWriterMessageDataType));
29117 defaultUadpConfiguration.dataSetMessageContentMask = (UA_UadpDataSetMessageContentMask)
29118 ((u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP |
29119 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION |
29120 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION);
29121 dsm = &defaultUadpConfiguration; /* type is UADP */
29122 }
29123
29124 /* The field encoding depends on the flags inside the writer config. */
29125 if(dataSetWriter->config.dataSetFieldContentMask &
29126 (u64)UA_DATASETFIELDCONTENTMASK_RAWDATA) {
29127 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
29128 } else if((u64)dataSetWriter->config.dataSetFieldContentMask &
29129 ((u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP |
29130 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS |
29131 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS |
29132 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE)) {
29133 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
29134 } else {
29135 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
29136 }
29137
29138 if(dsm) {
29139 /* Sanity-test the configuration */
29140 if(dsm->networkMessageNumber != 0 ||
29141 dsm->dataSetOffset != 0 ||
29142 dsm->configuredSize != 0) {
29143 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29144 "Static DSM configuration not supported. Using defaults");
29145 dsm->networkMessageNumber = 0;
29146 dsm->dataSetOffset = 0;
29147 dsm->configuredSize = 0;
29148 }
29149
29150 /* Std: 'The DataSetMessageContentMask defines the flags for the content
29151 * of the DataSetMessage header.' */
29152 if((u64)dsm->dataSetMessageContentMask &
29153 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION) {
29154 dataSetMessage->header.configVersionMajorVersionEnabled = true;
29155 dataSetMessage->header.configVersionMajorVersion =
29156 currentDataSet->dataSetMetaData.configurationVersion.majorVersion;
29157 }
29158 if((u64)dsm->dataSetMessageContentMask &
29159 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION) {
29160 dataSetMessage->header.configVersionMinorVersionEnabled = true;
29161 dataSetMessage->header.configVersionMinorVersion =
29162 currentDataSet->dataSetMetaData.configurationVersion.minorVersion;
29163 }
29164
29165 if((u64)dsm->dataSetMessageContentMask &
29166 (u64)UA_UADPDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
29167 dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
29168 dataSetMessage->header.dataSetMessageSequenceNr =
29169 dataSetWriter->actualDataSetMessageSequenceCount;
29170 }
29171
29172 if((u64)dsm->dataSetMessageContentMask &
29173 (u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP) {
29174 dataSetMessage->header.timestampEnabled = true;
29175 dataSetMessage->header.timestamp = UA_DateTime_now();
29176 }
29177
29178 /* TODO: Picoseconds resolution not supported atm */
29179 if((u64)dsm->dataSetMessageContentMask &
29180 (u64)UA_UADPDATASETMESSAGECONTENTMASK_PICOSECONDS) {
29181 dataSetMessage->header.picoSecondsIncluded = false;
29182 }
29183
29184 /* TODO: Statuscode not supported yet */
29185 if((u64)dsm->dataSetMessageContentMask &
29186 (u64)UA_UADPDATASETMESSAGECONTENTMASK_STATUS) {
29187 dataSetMessage->header.statusEnabled = true;
29188 }
29189 } else if(jsonDsm) {
29190 if((u64)jsonDsm->dataSetMessageContentMask &
29191 (u64)UA_JSONDATASETMESSAGECONTENTMASK_METADATAVERSION) {
29192 dataSetMessage->header.configVersionMajorVersionEnabled = true;
29193 dataSetMessage->header.configVersionMajorVersion =
29194 currentDataSet->dataSetMetaData.configurationVersion.majorVersion;
29195 }
29196 if((u64)jsonDsm->dataSetMessageContentMask &
29197 (u64)UA_JSONDATASETMESSAGECONTENTMASK_METADATAVERSION) {
29198 dataSetMessage->header.configVersionMinorVersionEnabled = true;
29199 dataSetMessage->header.configVersionMinorVersion =
29200 currentDataSet->dataSetMetaData.configurationVersion.minorVersion;
29201 }
29202
29203 if((u64)jsonDsm->dataSetMessageContentMask &
29204 (u64)UA_JSONDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
29205 dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
29206 dataSetMessage->header.dataSetMessageSequenceNr =
29207 dataSetWriter->actualDataSetMessageSequenceCount;
29208 }
29209
29210 if((u64)jsonDsm->dataSetMessageContentMask &
29211 (u64)UA_JSONDATASETMESSAGECONTENTMASK_TIMESTAMP) {
29212 dataSetMessage->header.timestampEnabled = true;
29213 dataSetMessage->header.timestamp = UA_DateTime_now();
29214 }
29215
29216 /* TODO: Statuscode not supported yet */
29217 if((u64)jsonDsm->dataSetMessageContentMask &
29218 (u64)UA_JSONDATASETMESSAGECONTENTMASK_STATUS) {
29219 dataSetMessage->header.statusEnabled = true;
29220 }
29221 }
29222
29223 /* Set the sequence count. Automatically rolls over to zero */
29224 dataSetWriter->actualDataSetMessageSequenceCount++;
29225
29226 /* JSON does not differ between deltaframes and keyframes, only keyframes
29227 * are currently used. */
29228 if(dsm) {
29229#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
29230 /* Check if the PublishedDataSet version has changed -> if yes flush the
29231 * lastValue store and send a KeyFrame */
29232 if(dataSetWriter->connectedDataSetVersion.majorVersion !=
29233 currentDataSet->dataSetMetaData.configurationVersion.majorVersion ||
29234 dataSetWriter->connectedDataSetVersion.minorVersion !=
29235 currentDataSet->dataSetMetaData.configurationVersion.minorVersion) {
29236 /* Remove old samples */
29237 for(size_t i = 0; i < dataSetWriter->lastSamplesCount; i++)
29238 UA_DataValue_clear(&dataSetWriter->lastSamples[i].value);
29239
29240 /* Realloc PDS dependent memory */
29241 dataSetWriter->lastSamplesCount = currentDataSet->fieldSize;
29242 UA_DataSetWriterSample *newSamplesArray = (UA_DataSetWriterSample * )
29243 UA_realloc(dataSetWriter->lastSamples,
29244 sizeof(UA_DataSetWriterSample) * dataSetWriter->lastSamplesCount);
29245 if(!newSamplesArray)
29246 return UA_STATUSCODE_BADOUTOFMEMORY;
29247 dataSetWriter->lastSamples = newSamplesArray;
29248 memset(dataSetWriter->lastSamples, 0,
29249 sizeof(UA_DataSetWriterSample) * dataSetWriter->lastSamplesCount);
29250
29251 dataSetWriter->connectedDataSetVersion =
29252 currentDataSet->dataSetMetaData.configurationVersion;
29253 UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage,
29254 dataSetWriter);
29255 dataSetWriter->deltaFrameCounter = 0;
29256 return UA_STATUSCODE_GOOD;
29257 }
29258
29259 /* The standard defines: if a PDS contains only one fields no delta messages
29260 * should be generated because they need more memory than a keyframe with 1
29261 * field. */
29262 if(currentDataSet->fieldSize > 1 && dataSetWriter->deltaFrameCounter > 0 &&
29263 dataSetWriter->deltaFrameCounter <= dataSetWriter->config.keyFrameCount) {
29264 UA_PubSubDataSetWriter_generateDeltaFrameMessage(server, dataSetMessage,
29265 dataSetWriter);
29266 dataSetWriter->deltaFrameCounter++;
29267 return UA_STATUSCODE_GOOD;
29268 }
29269
29270 dataSetWriter->deltaFrameCounter = 1;
29271#endif
29272 }
29273
29274 return UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage,
29275 dataSetWriter);
29276}
29277
29278#endif /* UA_ENABLE_PUBSUB */
29279
29280/**** amalgamated original file "/src/pubsub/ua_pubsub_writergroup.c" ****/
29281
29282/* This Source Code Form is subject to the terms of the Mozilla Public
29283 * License, v. 2.0. If a copy of the MPL was not distributed with this
29284 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
29285 *
29286 * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
29287 * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
29288 * Copyright (c) 2019 Kalycito Infotech Private Limited
29289 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
29290 * Copyright (c) 2020 Thomas Fischer, Siemens AG
29291 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
29292 */
29293
29294
29295#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
29296
29297
29298#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
29299#endif
29300
29301#define UA_MAX_STACKBUF 128 /* Max size of network messages on the stack */
29302
29303static void
29304UA_WriterGroup_clear(UA_Server *server, UA_WriterGroup *writerGroup);
29305
29306static UA_StatusCode
29307generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
29308 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount,
29309 UA_ExtensionObject *messageSettings,
29310 UA_ExtensionObject *transportSettings,
29311 UA_NetworkMessage *networkMessage);
29312
29313UA_StatusCode
29314UA_Server_addWriterGroup(UA_Server *server, const UA_NodeId connection,
29315 const UA_WriterGroupConfig *writerGroupConfig,
29316 UA_NodeId *writerGroupIdentifier) {
29317 if(!writerGroupConfig)
29318 return UA_STATUSCODE_BADINVALIDARGUMENT;
29319
29320 /* Search the connection by the given connectionIdentifier */
29321 UA_PubSubConnection *currentConnectionContext =
29322 UA_PubSubConnection_findConnectionbyId(server, connection);
29323 if(!currentConnectionContext)
29324 return UA_STATUSCODE_BADNOTFOUND;
29325
29326 if(currentConnectionContext->configurationFrozen){
29327 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29328 "Adding WriterGroup failed. PubSubConnection is frozen.");
29329 return UA_STATUSCODE_BADCONFIGURATIONERROR;
29330 }
29331
29332 /* Validate messageSettings type */
29333 const UA_ExtensionObject *ms = &writerGroupConfig->messageSettings;
29334 if(ms->content.decoded.type) {
29335 if(writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_JSON &&
29336 (ms->encoding != UA_EXTENSIONOBJECT_DECODED ||
29337 ms->content.decoded.type != &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE])) {
29338 return UA_STATUSCODE_BADTYPEMISMATCH;
29339 }
29340
29341 if(writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_UADP &&
29342 (ms->encoding != UA_EXTENSIONOBJECT_DECODED ||
29343 ms->content.decoded.type != &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])) {
29344 return UA_STATUSCODE_BADTYPEMISMATCH;
29345 }
29346 }
29347
29348 /* Allocate new WriterGroup */
29349 UA_WriterGroup *newWriterGroup = (UA_WriterGroup*)UA_calloc(1, sizeof(UA_WriterGroup));
29350 if(!newWriterGroup)
29351 return UA_STATUSCODE_BADOUTOFMEMORY;
29352
29353 newWriterGroup->componentType = UA_PUBSUB_COMPONENT_WRITERGROUP;
29354 newWriterGroup->linkedConnection = currentConnectionContext;
29355
29356 /* Deep copy of the config */
29357 UA_WriterGroupConfig *newConfig = &newWriterGroup->config;
29358 UA_StatusCode res = UA_WriterGroupConfig_copy(writerGroupConfig, newConfig);
29359 if(res != UA_STATUSCODE_GOOD) {
29360 UA_free(newWriterGroup);
29361 return res;
29362 }
29363
29364 /* Create the datatype value if not present */
29365 if(!newConfig->messageSettings.content.decoded.type) {
29366 UA_UadpWriterGroupMessageDataType *wgm = UA_UadpWriterGroupMessageDataType_new();
29367 newConfig->messageSettings.content.decoded.data = wgm;
29368 newConfig->messageSettings.content.decoded.type =
29369 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
29370 newConfig->messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
29371 }
29372
29373 /* Attach to the connection */
29374 LIST_INSERT_HEAD(&currentConnectionContext->writerGroups, newWriterGroup, listEntry);
29375 currentConnectionContext->writerGroupsSize++;
29376
29377 /* Add representation / create unique identifier */
29378#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
29379 res = addWriterGroupRepresentation(server, newWriterGroup);
29380#else
29381 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
29382 &newWriterGroup->identifier);
29383#endif
29384 if(writerGroupIdentifier)
29385 UA_NodeId_copy(&newWriterGroup->identifier, writerGroupIdentifier);
29386 return res;
29387}
29388
29389UA_StatusCode
29390UA_Server_removeWriterGroup(UA_Server *server, const UA_NodeId writerGroup) {
29391 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29392 if(!wg)
29393 return UA_STATUSCODE_BADNOTFOUND;
29394
29395 if(wg->configurationFrozen) {
29396 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29397 "Delete WriterGroup failed. WriterGroup is frozen.");
29398 return UA_STATUSCODE_BADCONFIGURATIONERROR;
29399 }
29400
29401 UA_PubSubConnection *connection = wg->linkedConnection;
29402 if(!connection)
29403 return UA_STATUSCODE_BADNOTFOUND;
29404
29405 if(connection->configurationFrozen) {
29406 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29407 "Delete WriterGroup failed. PubSubConnection is frozen.");
29408 return UA_STATUSCODE_BADCONFIGURATIONERROR;
29409 }
29410
29411 if(wg->state == UA_PUBSUBSTATE_OPERATIONAL) {
29412 /* Unregister the publish callback */
29413 if(wg->config.pubsubManagerCallback.removeCustomCallback)
29414 wg->config.pubsubManagerCallback.
29415 removeCustomCallback(server, wg->identifier, wg->publishCallbackId);
29416 else
29417 UA_PubSubManager_removeRepeatedPubSubCallback(server, wg->publishCallbackId);
29418
29419 }
29420
29421 UA_DataSetWriter *dsw, *dsw_tmp;
29422 LIST_FOREACH_SAFE(dsw, &wg->writers, listEntry, dsw_tmp) {
29423 UA_DataSetWriter_remove(server, wg, dsw);
29424 }
29425
29426 connection->writerGroupsSize--;
29427#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
29428 removeGroupRepresentation(server, wg);
29429#endif
29430
29431 UA_WriterGroup_clear(server, wg);
29432 LIST_REMOVE(wg, listEntry);
29433 UA_free(wg);
29434 return UA_STATUSCODE_GOOD;
29435}
29436
29437UA_StatusCode
29438UA_Server_freezeWriterGroupConfiguration(UA_Server *server,
29439 const UA_NodeId writerGroup) {
29440 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29441 if(!wg)
29442 return UA_STATUSCODE_BADNOTFOUND;
29443
29444 /* PubSubConnection freezeCounter++ */
29445 UA_PubSubConnection *pubSubConnection = wg->linkedConnection;
29446 pubSubConnection->configurationFreezeCounter++;
29447 pubSubConnection->configurationFrozen = true;
29448
29449 /* WriterGroup freeze */
29450 wg->configurationFrozen = true;
29451
29452 /* DataSetWriter freeze */
29453 UA_DataSetWriter *dataSetWriter;
29454 LIST_FOREACH(dataSetWriter, &wg->writers, listEntry) {
29455 dataSetWriter->configurationFrozen = true;
29456 /* PublishedDataSet freezeCounter++ */
29457 UA_PublishedDataSet *publishedDataSet =
29458 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
29459 publishedDataSet->configurationFreezeCounter++;
29460 publishedDataSet->configurationFrozen = true;
29461 /* DataSetFields freeze */
29462 UA_DataSetField *dataSetField;
29463 TAILQ_FOREACH(dataSetField, &publishedDataSet->fields, listEntry) {
29464 dataSetField->configurationFrozen = true;
29465 }
29466 }
29467
29468 if(wg->config.rtLevel != UA_PUBSUB_RT_FIXED_SIZE)
29469 return UA_STATUSCODE_GOOD;
29470
29471 /* Freeze the RT writer configuration */
29472 size_t dsmCount = 0;
29473 if(wg->config.encodingMimeType != UA_PUBSUB_ENCODING_UADP) {
29474 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29475 "PubSub-RT configuration fail: Non-RT capable encoding.");
29476 return UA_STATUSCODE_BADNOTSUPPORTED;
29477 }
29478
29479 //TODO Clarify: should we only allow = maxEncapsulatedDataSetMessageCount == 1 with RT?
29480 //TODO Clarify: Behaviour if the finale size is more than MTU
29481
29482 /* Generate data set messages */
29483 UA_STACKARRAY(UA_UInt16, dsWriterIds, wg->writersCount);
29484 UA_STACKARRAY(UA_DataSetMessage, dsmStore, wg->writersCount);
29485 UA_StatusCode res = UA_STATUSCODE_GOOD;
29486 UA_DataSetWriter *dsw;
29487 LIST_FOREACH(dsw, &wg->writers, listEntry) {
29488 /* Find the dataset */
29489 UA_PublishedDataSet *pds =
29490 UA_PublishedDataSet_findPDSbyId(server, dsw->connectedDataSet);
29491 if(!pds) {
29492 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29493 "PubSub Publish: PublishedDataSet not found");
29494 continue;
29495 }
29496 if(pds->promotedFieldsCount > 0) {
29497 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29498 "PubSub-RT configuration fail: PDS contains promoted fields.");
29499 return UA_STATUSCODE_BADNOTSUPPORTED;
29500 }
29501
29502 /* Test the DataSetFields */
29503 UA_DataSetField *dsf;
29504 TAILQ_FOREACH(dsf, &pds->fields, listEntry) {
29505 const UA_VariableNode *rtNode = (const UA_VariableNode *)
29506 UA_NODESTORE_GET(server, &dsf->config.field.variable.publishParameters.publishedVariable);
29507 if(rtNode != NULL && rtNode->valueBackend.backendType != UA_VALUEBACKENDTYPE_EXTERNAL) {
29508 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29509 "PubSub-RT configuration fail: PDS contains field without external data source.");
29510 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
29511 return UA_STATUSCODE_BADNOTSUPPORTED;
29512 }
29513 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
29514 if((UA_NodeId_equal(&dsf->fieldMetaData.dataType, &UA_TYPES[UA_TYPES_STRING].typeId) ||
29515 UA_NodeId_equal(&dsf->fieldMetaData.dataType,
29516 &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) &&
29517 dsf->fieldMetaData.maxStringLength == 0) {
29518 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29519 "PubSub-RT configuration fail: "
29520 "PDS contains String/ByteString with dynamic length.");
29521 return UA_STATUSCODE_BADNOTSUPPORTED;
29522 } else if(!UA_DataType_isNumeric(UA_findDataType(&dsf->fieldMetaData.dataType)) &&
29523 !UA_NodeId_equal(&dsf->fieldMetaData.dataType, &UA_TYPES[UA_TYPES_BOOLEAN].typeId)) {
29524 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29525 "PubSub-RT configuration fail: "
29526 "PDS contains variable with dynamic size.");
29527 return UA_STATUSCODE_BADNOTSUPPORTED;
29528 }
29529 }
29530
29531 /* Generate the DSM */
29532 res = UA_DataSetWriter_generateDataSetMessage(server, &dsmStore[dsmCount], dsw);
29533 if(res != UA_STATUSCODE_GOOD) {
29534 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29535 "PubSub RT Offset calculation: DataSetMessage buffering failed");
29536 continue;
29537 }
29538
29539 dsWriterIds[dsmCount] = dsw->config.dataSetWriterId;
29540 dsmCount++;
29541 }
29542
29543 /* Define variables here for goto */
29544 size_t msgSize;
29545 UA_ByteString buf;
29546 UA_NetworkMessage networkMessage;
29547 const UA_Byte *bufEnd;
29548 UA_Byte *bufPos;
29549
29550 if(res != UA_STATUSCODE_GOOD)
29551 goto cleanup_dsm;
29552
29553 memset(&networkMessage, 0, sizeof(networkMessage));
29554 res = generateNetworkMessage(pubSubConnection, wg, dsmStore, dsWriterIds,
29555 (UA_Byte) dsmCount, &wg->config.messageSettings,
29556 &wg->config.transportSettings, &networkMessage);
29557 if(res != UA_STATUSCODE_GOOD)
29558 goto cleanup_dsm;
29559
29560 /* Generate the offset-buffer (done inside calcSizeBinary) */
29561 memset(&wg->bufferedMessage, 0, sizeof(UA_NetworkMessageOffsetBuffer));
29562 UA_NetworkMessage_calcSizeBinary(&networkMessage, &wg->bufferedMessage);
29563
29564 /* Allocate the buffer. Allocate on the stack if the buffer is small. */
29565 msgSize = UA_NetworkMessage_calcSizeBinary(&networkMessage, NULL);
29566 res = UA_ByteString_allocBuffer(&buf, msgSize);
29567 if(res != UA_STATUSCODE_GOOD)
29568 goto cleanup;
29569 wg->bufferedMessage.buffer = buf;
29570
29571 /* Encode the NetworkMessage */
29572 bufEnd = &wg->bufferedMessage.buffer.data[wg->bufferedMessage.buffer.length];
29573 bufPos = wg->bufferedMessage.buffer.data;
29574 UA_NetworkMessage_encodeBinary(&networkMessage, &bufPos, bufEnd, NULL);
29575
29576 cleanup:
29577 UA_free(networkMessage.payload.dataSetPayload.sizes);
29578
29579 /* Clean up DSM */
29580 cleanup_dsm:
29581 for(size_t i = 0; i < dsmCount; i++){
29582 UA_free(dsmStore[i].data.keyFrameData.dataSetFields);
29583#ifdef UA_ENABLE_JSON_ENCODING
29584 UA_Array_delete(dsmStore[i].data.keyFrameData.fieldNames,
29585 dsmStore[i].data.keyFrameData.fieldCount,
29586 &UA_TYPES[UA_TYPES_STRING]);
29587#endif
29588 }
29589
29590 return res;
29591}
29592
29593UA_StatusCode
29594UA_Server_unfreezeWriterGroupConfiguration(UA_Server *server,
29595 const UA_NodeId writerGroup) {
29596 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29597 if(!wg)
29598 return UA_STATUSCODE_BADNOTFOUND;
29599 //if(wg->config.rtLevel == UA_PUBSUB_RT_NONE){
29600 // UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29601 // "PubSub configuration freeze without RT configuration has no effect.");
29602 // return UA_STATUSCODE_BADCONFIGURATIONERROR;
29603 //}
29604 //PubSubConnection freezeCounter--
29605 UA_PubSubConnection *pubSubConnection = wg->linkedConnection;
29606 pubSubConnection->configurationFreezeCounter--;
29607 if(pubSubConnection->configurationFreezeCounter == 0){
29608 pubSubConnection->configurationFrozen = UA_FALSE;
29609 }
29610 //WriterGroup unfreeze
29611 wg->configurationFrozen = UA_FALSE;
29612 //DataSetWriter unfreeze
29613 UA_DataSetWriter *dataSetWriter;
29614 LIST_FOREACH(dataSetWriter, &wg->writers, listEntry) {
29615 UA_PublishedDataSet *publishedDataSet =
29616 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
29617 //PublishedDataSet freezeCounter--
29618 publishedDataSet->configurationFreezeCounter--;
29619 if(publishedDataSet->configurationFreezeCounter == 0){
29620 publishedDataSet->configurationFrozen = UA_FALSE;
29621 UA_DataSetField *dataSetField;
29622 TAILQ_FOREACH(dataSetField, &publishedDataSet->fields, listEntry){
29623 dataSetField->configurationFrozen = UA_FALSE;
29624 }
29625 }
29626 dataSetWriter->configurationFrozen = UA_FALSE;
29627 }
29628
29629 UA_NetworkMessageOffsetBuffer_clear(&wg->bufferedMessage);
29630
29631 return UA_STATUSCODE_GOOD;
29632}
29633
29634UA_StatusCode
29635UA_Server_setWriterGroupOperational(UA_Server *server,
29636 const UA_NodeId writerGroup) {
29637 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29638 if(!wg)
29639 return UA_STATUSCODE_BADNOTFOUND;
29640 return UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, wg);
29641}
29642
29643UA_StatusCode
29644UA_Server_setWriterGroupDisabled(UA_Server *server,
29645 const UA_NodeId writerGroup) {
29646 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29647 if(!wg)
29648 return UA_STATUSCODE_BADNOTFOUND;
29649 return UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, wg);
29650}
29651
29652UA_StatusCode
29653UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src,
29654 UA_WriterGroupConfig *dst){
29655 UA_StatusCode res = UA_STATUSCODE_GOOD;
29656 memcpy(dst, src, sizeof(UA_WriterGroupConfig));
29657 res |= UA_String_copy(&src->name, &dst->name);
29658 res |= UA_ExtensionObject_copy(&src->transportSettings, &dst->transportSettings);
29659 res |= UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
29660 if(src->groupPropertiesSize > 0) {
29661 dst->groupProperties = (UA_KeyValuePair*)
29662 UA_calloc(src->groupPropertiesSize, sizeof(UA_KeyValuePair));
29663 if(!dst->groupProperties)
29664 return UA_STATUSCODE_BADOUTOFMEMORY;
29665 for(size_t i = 0; i < src->groupPropertiesSize; i++) {
29666 res |= UA_KeyValuePair_copy(&src->groupProperties[i], &dst->groupProperties[i]);
29667 }
29668 }
29669 if(res != UA_STATUSCODE_GOOD)
29670 UA_WriterGroupConfig_clear(dst);
29671 return res;
29672}
29673
29674UA_StatusCode
29675UA_Server_getWriterGroupConfig(UA_Server *server, const UA_NodeId writerGroup,
29676 UA_WriterGroupConfig *config) {
29677 if(!config)
29678 return UA_STATUSCODE_BADINVALIDARGUMENT;
29679 UA_WriterGroup *currentWG = UA_WriterGroup_findWGbyId(server, writerGroup);
29680 if(!currentWG)
29681 return UA_STATUSCODE_BADNOTFOUND;
29682 return UA_WriterGroupConfig_copy(&currentWG->config, config);
29683}
29684
29685UA_StatusCode
29686UA_Server_updateWriterGroupConfig(UA_Server *server, UA_NodeId writerGroupIdentifier,
29687 const UA_WriterGroupConfig *config){
29688 if(!config)
29689 return UA_STATUSCODE_BADINVALIDARGUMENT;
29690
29691 UA_WriterGroup *currentWriterGroup =
29692 UA_WriterGroup_findWGbyId(server, writerGroupIdentifier);
29693 if(!currentWriterGroup)
29694 return UA_STATUSCODE_BADNOTFOUND;
29695
29696 if(currentWriterGroup->configurationFrozen){
29697 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29698 "Modify WriterGroup failed. WriterGroup is frozen.");
29699 return UA_STATUSCODE_BADCONFIGURATIONERROR;
29700 }
29701
29702 //The update functionality will be extended during the next PubSub batches.
29703 //Currently is only a change of the publishing interval possible.
29704 if(currentWriterGroup->config.maxEncapsulatedDataSetMessageCount != config->maxEncapsulatedDataSetMessageCount) {
29705 currentWriterGroup->config.maxEncapsulatedDataSetMessageCount = config->maxEncapsulatedDataSetMessageCount;
29706 if(currentWriterGroup->config.messageSettings.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
29707 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29708 "MaxEncapsulatedDataSetMessag need enabled 'PayloadHeader' within the message settings.");
29709 }
29710 }
29711
29712 if(currentWriterGroup->config.publishingInterval != config->publishingInterval) {
29713 if(currentWriterGroup->config.rtLevel == UA_PUBSUB_RT_NONE &&
29714 currentWriterGroup->state == UA_PUBSUBSTATE_OPERATIONAL) {
29715 if(currentWriterGroup->config.pubsubManagerCallback.removeCustomCallback)
29716 currentWriterGroup->config.pubsubManagerCallback.
29717 removeCustomCallback(server, currentWriterGroup->identifier,
29718 currentWriterGroup->publishCallbackId);
29719 else
29720 UA_PubSubManager_removeRepeatedPubSubCallback(server, currentWriterGroup->publishCallbackId);
29721
29722 currentWriterGroup->config.publishingInterval = config->publishingInterval;
29723 UA_WriterGroup_addPublishCallback(server, currentWriterGroup);
29724 } else {
29725 currentWriterGroup->config.publishingInterval = config->publishingInterval;
29726 }
29727 }
29728
29729 if(currentWriterGroup->config.priority != config->priority) {
29730 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29731 "No or unsupported WriterGroup update.");
29732 }
29733
29734 return UA_STATUSCODE_GOOD;
29735}
29736
29737UA_StatusCode
29738UA_Server_WriterGroup_getState(UA_Server *server, UA_NodeId writerGroupIdentifier,
29739 UA_PubSubState *state) {
29740 if((server == NULL) || (state == NULL))
29741 return UA_STATUSCODE_BADINVALIDARGUMENT;
29742 UA_WriterGroup *currentWriterGroup =
29743 UA_WriterGroup_findWGbyId(server, writerGroupIdentifier);
29744 if(currentWriterGroup == NULL)
29745 return UA_STATUSCODE_BADNOTFOUND;
29746 *state = currentWriterGroup->state;
29747 return UA_STATUSCODE_GOOD;
29748}
29749
29750UA_WriterGroup *
29751UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier) {
29752 UA_PubSubConnection *tmpConnection;
29753 TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry) {
29754 UA_WriterGroup *tmpWriterGroup;
29755 LIST_FOREACH(tmpWriterGroup, &tmpConnection->writerGroups, listEntry) {
29756 if(UA_NodeId_equal(&identifier, &tmpWriterGroup->identifier))
29757 return tmpWriterGroup;
29758 }
29759 }
29760 return NULL;
29761}
29762
29763#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
29764UA_StatusCode
29765UA_Server_setWriterGroupEncryptionKeys(UA_Server *server, const UA_NodeId writerGroup,
29766 UA_UInt32 securityTokenId,
29767 const UA_ByteString signingKey,
29768 const UA_ByteString encryptingKey,
29769 const UA_ByteString keyNonce) {
29770 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29771 if(!wg)
29772 return UA_STATUSCODE_BADNOTFOUND;
29773
29774 if(!wg->config.securityPolicy) {
29775 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29776 "No SecurityPolicy configured for the WriterGroup");
29777 return UA_STATUSCODE_BADINTERNALERROR;
29778 }
29779
29780 if(securityTokenId != wg->securityTokenId) {
29781 wg->securityTokenId = securityTokenId;
29782 wg->nonceSequenceNumber = 1;
29783 }
29784
29785 /* Create a new context */
29786 if(!wg->securityPolicyContext) {
29787 return wg->config.securityPolicy->
29788 newContext(wg->config.securityPolicy->policyContext,
29789 &signingKey, &encryptingKey, &keyNonce,
29790 &wg->securityPolicyContext);
29791 }
29792
29793 /* Update the context */
29794 return wg->config.securityPolicy->
29795 setSecurityKeys(wg->securityPolicyContext, &signingKey, &encryptingKey, &keyNonce);
29796}
29797#endif
29798
29799void
29800UA_WriterGroupConfig_clear(UA_WriterGroupConfig *writerGroupConfig){
29801 UA_String_clear(&writerGroupConfig->name);
29802 UA_ExtensionObject_clear(&writerGroupConfig->transportSettings);
29803 UA_ExtensionObject_clear(&writerGroupConfig->messageSettings);
29804 UA_Array_delete(writerGroupConfig->groupProperties,
29805 writerGroupConfig->groupPropertiesSize,
29806 &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
29807 writerGroupConfig->groupProperties = NULL;
29808}
29809
29810static void
29811UA_WriterGroup_clear(UA_Server *server, UA_WriterGroup *writerGroup) {
29812 UA_WriterGroupConfig_clear(&writerGroup->config);
29813 UA_NodeId_clear(&writerGroup->identifier);
29814
29815 /* Delete all writers */
29816 UA_DataSetWriter *dataSetWriter, *tmpDataSetWriter;
29817 LIST_FOREACH_SAFE(dataSetWriter, &writerGroup->writers, listEntry, tmpDataSetWriter){
29818 UA_Server_removeDataSetWriter(server, dataSetWriter->identifier);
29819 }
29820
29821 UA_NetworkMessageOffsetBuffer_clear(&writerGroup->bufferedMessage);
29822
29823#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
29824 if(writerGroup->config.securityPolicy && writerGroup->securityPolicyContext) {
29825 writerGroup->config.securityPolicy->deleteContext(writerGroup->securityPolicyContext);
29826 writerGroup->securityPolicyContext = NULL;
29827 }
29828#endif
29829}
29830
29831UA_StatusCode
29832UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
29833 UA_WriterGroup *writerGroup) {
29834 UA_DataSetWriter *dataSetWriter;
29835 switch(state) {
29836 case UA_PUBSUBSTATE_DISABLED:
29837 switch (writerGroup->state){
29838 case UA_PUBSUBSTATE_DISABLED:
29839 return UA_STATUSCODE_GOOD;
29840 case UA_PUBSUBSTATE_PAUSED:
29841 break;
29842 case UA_PUBSUBSTATE_OPERATIONAL:
29843 if(writerGroup->config.pubsubManagerCallback.removeCustomCallback)
29844 writerGroup->config.pubsubManagerCallback.
29845 removeCustomCallback(server, writerGroup->identifier, writerGroup->publishCallbackId);
29846 else
29847 UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
29848
29849 LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
29850 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, dataSetWriter);
29851 }
29852 writerGroup->state = UA_PUBSUBSTATE_DISABLED;
29853 break;
29854 case UA_PUBSUBSTATE_ERROR:
29855 break;
29856 default:
29857 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29858 "Received unknown PubSub state!");
29859 }
29860 break;
29861 case UA_PUBSUBSTATE_PAUSED:
29862 switch (writerGroup->state) {
29863 case UA_PUBSUBSTATE_DISABLED:
29864 break;
29865 case UA_PUBSUBSTATE_PAUSED:
29866 return UA_STATUSCODE_GOOD;
29867 case UA_PUBSUBSTATE_OPERATIONAL:
29868 break;
29869 case UA_PUBSUBSTATE_ERROR:
29870 break;
29871 default:
29872 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29873 "Received unknown PubSub state!");
29874 }
29875 break;
29876 case UA_PUBSUBSTATE_OPERATIONAL:
29877 switch (writerGroup->state) {
29878 case UA_PUBSUBSTATE_DISABLED:
29879 writerGroup->state = UA_PUBSUBSTATE_OPERATIONAL;
29880 if(writerGroup->config.pubsubManagerCallback.removeCustomCallback)
29881 writerGroup->config.pubsubManagerCallback.
29882 removeCustomCallback(server, writerGroup->identifier,
29883 writerGroup->publishCallbackId);
29884 else
29885 UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
29886
29887 LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
29888 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL,
29889 dataSetWriter);
29890 }
29891 UA_WriterGroup_addPublishCallback(server, writerGroup);
29892 break;
29893 case UA_PUBSUBSTATE_PAUSED:
29894 break;
29895 case UA_PUBSUBSTATE_OPERATIONAL:
29896 return UA_STATUSCODE_GOOD;
29897 case UA_PUBSUBSTATE_ERROR:
29898 break;
29899 default:
29900 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29901 "Received unknown PubSub state!");
29902 }
29903 break;
29904 case UA_PUBSUBSTATE_ERROR: {
29905 switch (writerGroup->state){
29906 case UA_PUBSUBSTATE_DISABLED:
29907 break;
29908 case UA_PUBSUBSTATE_PAUSED:
29909 break;
29910 case UA_PUBSUBSTATE_OPERATIONAL:
29911 UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
29912 LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
29913 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dataSetWriter);
29914 }
29915 break;
29916 case UA_PUBSUBSTATE_ERROR:
29917 return UA_STATUSCODE_GOOD;
29918 default:
29919 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29920 "Received unknown PubSub state!");
29921 }
29922 writerGroup->state = UA_PUBSUBSTATE_ERROR;
29923 /* TODO: WIP - example usage of pubsubStateChangeCallback -> inform
29924 * application about error state, reason param necessary */
29925 UA_ServerConfig *pConfig = UA_Server_getConfig(server);
29926 if(pConfig->pubSubConfig.stateChangeCallback != 0) {
29927 pConfig->pubSubConfig.
29928 stateChangeCallback(&writerGroup->identifier, UA_PUBSUBSTATE_ERROR,
29929 UA_STATUSCODE_BADINTERNALERROR);
29930 }
29931 break;
29932 }
29933 default:
29934 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29935 "Received unknown PubSub state!");
29936 }
29937 return UA_STATUSCODE_GOOD;
29938}
29939
29940#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
29941static UA_StatusCode
29942encryptAndSign(UA_WriterGroup *wg, const UA_NetworkMessage *nm,
29943 UA_Byte *signStart, UA_Byte *encryptStart,
29944 UA_Byte *msgEnd) {
29945 UA_StatusCode rv;
29946 void *channelContext = wg->securityPolicyContext;
29947
29948 if(nm->securityHeader.networkMessageEncrypted) {
29949 /* Set the temporary MessageNonce in the SecurityPolicy */
29950 rv = wg->config.securityPolicy->setMessageNonce(channelContext,
29951 &nm->securityHeader.messageNonce);
29952 UA_CHECK_STATUS(rv, return rv);
29953
29954 /* The encryption is done in-place, no need to encode again */
29955 UA_ByteString toBeEncrypted =
29956 {(uintptr_t)msgEnd - (uintptr_t)encryptStart, encryptStart};
29957 rv = wg->config.securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
29958 encrypt(channelContext, &toBeEncrypted);
29959 UA_CHECK_STATUS(rv, return rv);
29960 }
29961
29962 if(nm->securityHeader.networkMessageSigned) {
29963 UA_ByteString toBeSigned = {(uintptr_t)msgEnd - (uintptr_t)signStart,
29964 signStart};
29965
29966 size_t sigSize = wg->config.securityPolicy->symmetricModule.cryptoModule.
29967 signatureAlgorithm.getLocalSignatureSize(channelContext);
29968 UA_ByteString signature = {sigSize, msgEnd};
29969
29970 rv = wg->config.securityPolicy->symmetricModule.cryptoModule.
29971 signatureAlgorithm.sign(channelContext, &toBeSigned, &signature);
29972 UA_CHECK_STATUS(rv, return rv);
29973 }
29974 return UA_STATUSCODE_GOOD;
29975}
29976#endif
29977
29978static UA_StatusCode
29979encodeNetworkMessage(UA_WriterGroup *wg, UA_NetworkMessage *nm,
29980 UA_ByteString *buf) {
29981 UA_Byte *bufPos = buf->data;
29982 UA_Byte *bufEnd = &buf->data[buf->length];
29983
29984#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
29985 UA_Byte *networkMessageStart = bufPos;
29986#endif
29987 UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(nm, &bufPos, bufEnd);
29988 UA_CHECK_STATUS(rv, return rv);
29989
29990#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
29991 UA_Byte *payloadStart = bufPos;
29992#endif
29993 rv = UA_NetworkMessage_encodePayload(nm, &bufPos, bufEnd);
29994 UA_CHECK_STATUS(rv, return rv);
29995
29996 rv = UA_NetworkMessage_encodeFooters(nm, &bufPos, bufEnd);
29997 UA_CHECK_STATUS(rv, return rv);
29998
29999#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
30000 /* Encrypt and Sign the message */
30001 UA_Byte *footerEnd = bufPos;
30002 rv = encryptAndSign(wg, nm, networkMessageStart, payloadStart, footerEnd);
30003 UA_CHECK_STATUS(rv, return rv);
30004#endif
30005
30006 return UA_STATUSCODE_GOOD;
30007}
30008
30009#ifdef UA_ENABLE_JSON_ENCODING
30010static UA_StatusCode
30011sendNetworkMessageJson(UA_PubSubConnection *connection, UA_WriterGroup *wg,
30012 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
30013 /* Prepare the NetworkMessage */
30014 UA_NetworkMessage nm;
30015 memset(&nm, 0, sizeof(UA_NetworkMessage));
30016 nm.version = 1;
30017 nm.networkMessageType = UA_NETWORKMESSAGE_DATASET;
30018 nm.payloadHeaderEnabled = true;
30019 nm.payloadHeader.dataSetPayloadHeader.count = dsmCount;
30020 nm.payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerIds;
30021 nm.payload.dataSetPayload.dataSetMessages = dsm;
30022
30023 /* Compute the message length */
30024 size_t msgSize = UA_NetworkMessage_calcSizeJson(&nm, NULL, 0, NULL, 0, true);
30025
30026 /* Allocate the buffer. Allocate on the stack if the buffer is small. */
30027 UA_ByteString buf;
30028 UA_Byte stackBuf[UA_MAX_STACKBUF];
30029 buf.data = stackBuf;
30030 buf.length = msgSize;
30031 UA_StatusCode res = UA_STATUSCODE_GOOD;
30032 if(msgSize > UA_MAX_STACKBUF) {
30033 res = UA_ByteString_allocBuffer(&buf, msgSize);
30034 if(res != UA_STATUSCODE_GOOD)
30035 return res;
30036 }
30037
30038 /* Encode the message */
30039 UA_Byte *bufPos = buf.data;
30040 const UA_Byte *bufEnd = &buf.data[msgSize];
30041 res = UA_NetworkMessage_encodeJson(&nm, &bufPos, &bufEnd, NULL, 0, NULL, 0, true);
30042 if(res != UA_STATUSCODE_GOOD)
30043 goto cleanup;
30044 UA_assert(bufPos == bufEnd);
30045
30046 /* Send the prepared messages */
30047 res = connection->channel->send(connection->channel,
30048 &wg->config.transportSettings, &buf);
30049
30050 cleanup:
30051 if(msgSize > UA_MAX_STACKBUF)
30052 UA_ByteString_clear(&buf);
30053 return res;
30054}
30055#endif
30056
30057static UA_StatusCode
30058generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
30059 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount,
30060 UA_ExtensionObject *messageSettings,
30061 UA_ExtensionObject *transportSettings,
30062 UA_NetworkMessage *networkMessage) {
30063 if(messageSettings->content.decoded.type !=
30064 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])
30065 return UA_STATUSCODE_BADINTERNALERROR;
30066 UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*)
30067 messageSettings->content.decoded.data;
30068
30069 networkMessage->publisherIdEnabled =
30070 ((u64)wgm->networkMessageContentMask &
30071 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID) != 0;
30072 networkMessage->groupHeaderEnabled =
30073 ((u64)wgm->networkMessageContentMask &
30074 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER) != 0;
30075 networkMessage->groupHeader.writerGroupIdEnabled =
30076 ((u64)wgm->networkMessageContentMask &
30077 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID) != 0;
30078 networkMessage->groupHeader.groupVersionEnabled =
30079 ((u64)wgm->networkMessageContentMask &
30080 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPVERSION) != 0;
30081 networkMessage->groupHeader.networkMessageNumberEnabled =
30082 ((u64)wgm->networkMessageContentMask &
30083 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_NETWORKMESSAGENUMBER) != 0;
30084 networkMessage->groupHeader.sequenceNumberEnabled =
30085 ((u64)wgm->networkMessageContentMask &
30086 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_SEQUENCENUMBER) != 0;
30087 networkMessage->payloadHeaderEnabled =
30088 ((u64)wgm->networkMessageContentMask &
30089 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER) != 0;
30090 networkMessage->timestampEnabled =
30091 ((u64)wgm->networkMessageContentMask &
30092 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_TIMESTAMP) != 0;
30093 networkMessage->picosecondsEnabled =
30094 ((u64)wgm->networkMessageContentMask &
30095 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PICOSECONDS) != 0;
30096 networkMessage->dataSetClassIdEnabled =
30097 ((u64)wgm->networkMessageContentMask &
30098 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_DATASETCLASSID) != 0;
30099 networkMessage->promotedFieldsEnabled =
30100 ((u64)wgm->networkMessageContentMask &
30101 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PROMOTEDFIELDS) != 0;
30102
30103 /* Set the SecurityHeader */
30104#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
30105 if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) {
30106 networkMessage->securityEnabled = true;
30107 networkMessage->securityHeader.networkMessageSigned = true;
30108 if(wg->config.securityMode >= UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
30109 networkMessage->securityHeader.networkMessageEncrypted = true;
30110 networkMessage->securityHeader.securityTokenId = wg->securityTokenId;
30111
30112 /* Generate the MessageNonce */
30113 UA_ByteString_allocBuffer(&networkMessage->securityHeader.messageNonce, 8);
30114 if(networkMessage->securityHeader.messageNonce.length == 0)
30115 return UA_STATUSCODE_BADOUTOFMEMORY;
30116
30117 networkMessage->securityHeader.messageNonce.length = 4; /* Generate 4 random bytes */
30118 UA_StatusCode rv = wg->config.securityPolicy->symmetricModule.
30119 generateNonce(wg->config.securityPolicy->policyContext,
30120 &networkMessage->securityHeader.messageNonce);
30121 if(rv != UA_STATUSCODE_GOOD)
30122 return rv;
30123 networkMessage->securityHeader.messageNonce.length = 8;
30124 UA_Byte *pos = &networkMessage->securityHeader.messageNonce.data[4];
30125 const UA_Byte *end = &networkMessage->securityHeader.messageNonce.data[8];
30126 UA_UInt32_encodeBinary(&wg->nonceSequenceNumber, &pos, end);
30127 }
30128#endif
30129
30130 networkMessage->version = 1;
30131 networkMessage->networkMessageType = UA_NETWORKMESSAGE_DATASET;
30132 if(connection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_NUMERIC) {
30133 networkMessage->publisherIdType = UA_PUBLISHERDATATYPE_UINT16;
30134 networkMessage->publisherId.publisherIdUInt32 =
30135 connection->config->publisherId.numeric;
30136 } else if(connection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING) {
30137 networkMessage->publisherIdType = UA_PUBLISHERDATATYPE_STRING;
30138 networkMessage->publisherId.publisherIdString =
30139 connection->config->publisherId.string;
30140 }
30141
30142 if(networkMessage->groupHeader.sequenceNumberEnabled)
30143 networkMessage->groupHeader.sequenceNumber = wg->sequenceNumber;
30144
30145 if(networkMessage->groupHeader.groupVersionEnabled)
30146 networkMessage->groupHeader.groupVersion = wgm->groupVersion;
30147
30148 /* Compute the length of the dsm separately for the header */
30149 UA_UInt16 *dsmLengths = (UA_UInt16 *) UA_calloc(dsmCount, sizeof(UA_UInt16));
30150 if(!dsmLengths)
30151 return UA_STATUSCODE_BADOUTOFMEMORY;
30152 for(UA_Byte i = 0; i < dsmCount; i++)
30153 dsmLengths[i] = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&dsm[i], NULL, 0);
30154
30155 networkMessage->payloadHeader.dataSetPayloadHeader.count = dsmCount;
30156 networkMessage->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerIds;
30157 networkMessage->groupHeader.writerGroupId = wg->config.writerGroupId;
30158 /* number of the NetworkMessage inside a PublishingInterval */
30159 networkMessage->groupHeader.networkMessageNumber = 1;
30160 networkMessage->payload.dataSetPayload.sizes = dsmLengths;
30161 networkMessage->payload.dataSetPayload.dataSetMessages = dsm;
30162 return UA_STATUSCODE_GOOD;
30163}
30164
30165static UA_StatusCode
30166sendNetworkMessageBinary(UA_PubSubConnection *connection, UA_WriterGroup *wg,
30167 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
30168 UA_NetworkMessage nm;
30169 memset(&nm, 0, sizeof(UA_NetworkMessage));
30170
30171 /* Fill the message structure */
30172 UA_StatusCode rv =
30173 generateNetworkMessage(connection, wg, dsm, writerIds, dsmCount,
30174 &wg->config.messageSettings,
30175 &wg->config.transportSettings, &nm);
30176 UA_CHECK_STATUS(rv, return rv);
30177
30178 /* Compute the message size. Add the overhead for the security signature.
30179 * There is no padding and the encryption incurs no size overhead. */
30180 size_t msgSize = UA_NetworkMessage_calcSizeBinary(&nm, NULL);
30181#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
30182 if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) {
30183 UA_PubSubSecurityPolicy *sp = wg->config.securityPolicy;
30184 msgSize += sp->symmetricModule.cryptoModule.
30185 signatureAlgorithm.getLocalSignatureSize(sp->policyContext);
30186 }
30187#endif
30188
30189 /* Allocate the buffer. Allocate on the stack if the buffer is small. */
30190 UA_ByteString buf;
30191 UA_Byte stackBuf[UA_MAX_STACKBUF];
30192 buf.data = stackBuf;
30193 buf.length = msgSize;
30194 if(msgSize > UA_MAX_STACKBUF) {
30195 rv = UA_ByteString_allocBuffer(&buf, msgSize);
30196 UA_CHECK_STATUS(rv, goto cleanup);
30197 }
30198
30199 /* Encode and encrypt the message */
30200 rv = encodeNetworkMessage(wg, &nm, &buf);
30201 UA_CHECK_STATUS(rv, goto cleanup_with_msg_size);
30202
30203 /* Send out the message */
30204 rv = connection->channel->send(connection->channel,
30205 &wg->config.transportSettings, &buf);
30206 UA_CHECK_STATUS(rv, goto cleanup_with_msg_size);
30207
30208cleanup_with_msg_size:
30209 if(msgSize > UA_MAX_STACKBUF) {
30210 UA_ByteString_clear(&buf);
30211 }
30212cleanup:
30213 UA_ByteString_clear(&nm.securityHeader.messageNonce);
30214 UA_free(nm.payload.dataSetPayload.sizes);
30215 return rv;
30216}
30217
30218static void
30219sendNetworkMessage(UA_Server *server, UA_WriterGroup *wg, UA_PubSubConnection *connection,
30220 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
30221 UA_StatusCode res = UA_STATUSCODE_GOOD;
30222 switch(wg->config.encodingMimeType) {
30223 case UA_PUBSUB_ENCODING_UADP:
30224 res = sendNetworkMessageBinary(connection, wg, dsm, writerIds, dsmCount);
30225 break;
30226#ifdef UA_ENABLE_JSON_ENCODING
30227 case UA_PUBSUB_ENCODING_JSON:
30228 res = sendNetworkMessageJson(connection, wg, dsm, writerIds, dsmCount);
30229 break;
30230#endif
30231 default:
30232 res = UA_STATUSCODE_BADNOTSUPPORTED;
30233 break;
30234 }
30235
30236 /* If sending failed, disable all writer of the writergroup */
30237 if(res != UA_STATUSCODE_GOOD) {
30238 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30239 "PubSub Publish: Could not send a NetworkMessage "
30240 "with status code %s", UA_StatusCode_name(res));
30241 UA_DataSetWriter *dsw;
30242 LIST_FOREACH(dsw, &wg->writers, listEntry) {
30243 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
30244 }
30245 return;
30246 }
30247
30248 /* Increase the sequence number */
30249 wg->sequenceNumber++;
30250}
30251
30252static void
30253sendBufferedNetworkMessage(UA_Server *server, UA_WriterGroup *wg,
30254 UA_PubSubConnection *connection) {
30255 UA_NetworkMessageOffsetBuffer *buf = &wg->bufferedMessage;
30256 UA_StatusCode res = UA_NetworkMessage_updateBufferedMessage(buf);
30257 if(res != UA_STATUSCODE_GOOD) {
30258 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
30259 "PubSub sending failed - could not update the message");
30260 UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, wg);
30261 return;
30262 }
30263
30264 res = connection->channel->send(connection->channel,
30265 &wg->config.transportSettings, &buf->buffer);
30266 if(res != UA_STATUSCODE_GOOD) {
30267 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30268 "Publish failed. RT fixed size. sendBufferedNetworkMessage failed");
30269 UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, wg);
30270 return;
30271 }
30272
30273 /* Sending successful - increase the sequence number */
30274 wg->sequenceNumber++;
30275}
30276
30277/* This callback triggers the collection and publish of NetworkMessages and the
30278 * contained DataSetMessages. */
30279void
30280UA_WriterGroup_publishCallback(UA_Server *server, UA_WriterGroup *writerGroup) {
30281 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER, "Publish Callback");
30282
30283 // TODO: review if its okay to force correct value from caller side instead
30284 // UA_assert(writerGroup != NULL);
30285 // UA_assert(server != NULL);
30286
30287 if(!writerGroup) {
30288 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30289 "Publish failed. WriterGroup not found");
30290 return;
30291 }
30292
30293 /* Nothing to do? */
30294 if(writerGroup->writersCount == 0)
30295 return;
30296
30297 /* Find the connection associated with the writer */
30298 UA_PubSubConnection *connection = writerGroup->linkedConnection;
30299 if(!connection) {
30300 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30301 "Publish failed. PubSubConnection invalid.");
30302 UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, writerGroup);
30303 return;
30304 }
30305
30306 /* Realtime path - update the buffer message and send directly */
30307 if(writerGroup->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
30308 sendBufferedNetworkMessage(server, writerGroup, connection);
30309 return;
30310 }
30311
30312 /* How many DSM can be sent in one NM? */
30313 UA_Byte maxDSM = (UA_Byte)writerGroup->config.maxEncapsulatedDataSetMessageCount;
30314 if(writerGroup->config.maxEncapsulatedDataSetMessageCount > UA_BYTE_MAX)
30315 maxDSM = UA_BYTE_MAX;
30316
30317 /* If the maxEncapsulatedDataSetMessageCount is set to 0 -> 1 */
30318 if(maxDSM == 0)
30319 maxDSM = 1;
30320
30321 /* It is possible to put several DataSetMessages into one NetworkMessage.
30322 * But only if they do not contain promoted fields. NM with promoted fields
30323 * are sent out right away. The others are kept in a buffer for
30324 * "batching". */
30325 size_t dsmCount = 0;
30326 UA_STACKARRAY(UA_UInt16, dsWriterIds, writerGroup->writersCount);
30327 UA_STACKARRAY(UA_DataSetMessage, dsmStore, writerGroup->writersCount);
30328
30329 UA_DataSetWriter *dsw;
30330 LIST_FOREACH(dsw, &writerGroup->writers, listEntry) {
30331 if(dsw->state != UA_PUBSUBSTATE_OPERATIONAL)
30332 continue;
30333
30334 /* Find the dataset */
30335 UA_PublishedDataSet *pds =
30336 UA_PublishedDataSet_findPDSbyId(server, dsw->connectedDataSet);
30337 if(!pds) {
30338 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30339 "PubSub Publish: PublishedDataSet not found");
30340 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
30341 continue;
30342 }
30343
30344 /* Generate the DSM */
30345 dsWriterIds[dsmCount] = dsw->config.dataSetWriterId;
30346 UA_StatusCode res =
30347 UA_DataSetWriter_generateDataSetMessage(server, &dsmStore[dsmCount], dsw);
30348 if(res != UA_STATUSCODE_GOOD) {
30349 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30350 "PubSub Publish: DataSetMessage creation failed");
30351 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
30352 continue;
30353 }
30354
30355 /* There is no promoted field -> send right away */
30356 if(pds->promotedFieldsCount > 0) {
30357 sendNetworkMessage(server, writerGroup, connection, &dsmStore[dsmCount],
30358 &dsWriterIds[dsmCount], 1);
30359
30360 /* Clean up the current store entry */
30361 if(writerGroup->config.rtLevel == UA_PUBSUB_RT_DIRECT_VALUE_ACCESS) {
30362 for(size_t i = 0; i < dsmStore[dsmCount].data.keyFrameData.fieldCount; ++i) {
30363 dsmStore[dsmCount].data.keyFrameData.dataSetFields[i].value.data = NULL;
30364 }
30365 }
30366 UA_DataSetMessage_clear(&dsmStore[dsmCount]);
30367
30368 continue; /* Don't increase the dsmCount, reuse the slot */
30369 }
30370
30371 dsmCount++;
30372 }
30373
30374 /* Send the NetworkMessages with batched DataSetMessages */
30375 UA_Byte nmDsmCount = 0;
30376 for(size_t i = 0; i < dsmCount; i += nmDsmCount) {
30377 /* How many dsm are batched in this iteration? */
30378 nmDsmCount = (i + maxDSM > dsmCount) ? (UA_Byte)(dsmCount - i) : maxDSM;
30379
30380 /* Send the batched messages */
30381 sendNetworkMessage(server, writerGroup, connection, &dsmStore[i],
30382 &dsWriterIds[i], nmDsmCount);
30383 }
30384
30385 /* Clean up DSM */
30386 for(size_t i = 0; i < dsmCount; i++) {
30387 if(writerGroup->config.rtLevel == UA_PUBSUB_RT_DIRECT_VALUE_ACCESS) {
30388 for(size_t j = 0; j < dsmStore[i].data.keyFrameData.fieldCount; ++j) {
30389 dsmStore[i].data.keyFrameData.dataSetFields[j].value.data = NULL;
30390 }
30391 }
30392 UA_DataSetMessage_clear(&dsmStore[i]);
30393 }
30394}
30395
30396/* Add new publishCallback. The first execution is triggered directly after
30397 * creation. */
30398UA_StatusCode
30399UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup) {
30400 UA_StatusCode retval = UA_STATUSCODE_GOOD;
30401 if(writerGroup->config.pubsubManagerCallback.addCustomCallback)
30402 retval |= writerGroup->config.pubsubManagerCallback.
30403 addCustomCallback(server, writerGroup->identifier,
30404 (UA_ServerCallback) UA_WriterGroup_publishCallback,
30405 writerGroup, writerGroup->config.publishingInterval,
30406 NULL, // TODO: Send base time from writer group config
30407 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, // TODO: Send timer policy from writer group config
30408 &writerGroup->publishCallbackId);
30409 else
30410 retval |= UA_PubSubManager_addRepeatedCallback(server,
30411 (UA_ServerCallback) UA_WriterGroup_publishCallback,
30412 writerGroup, writerGroup->config.publishingInterval,
30413 NULL, // TODO: Send base time from writer group config
30414 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, // TODO: Send timer policy from writer group config
30415 &writerGroup->publishCallbackId);
30416
30417 if(retval == UA_STATUSCODE_GOOD)
30418 writerGroup->publishCallbackIsRegistered = true;
30419
30420 /* Run once after creation */
30421 UA_WriterGroup_publishCallback(server, writerGroup);
30422 return retval;
30423}
30424
30425#endif /* UA_ENABLE_PUBSUB */
30426
30427/**** amalgamated original file "/src/pubsub/ua_pubsub_reader.c" ****/
30428
30429/* This Source Code Form is subject to the terms of the Mozilla Public
30430 * License, v. 2.0. If a copy of the MPL was not distributed with this
30431 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
30432 *
30433 * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
30434 * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
30435 * Copyright (c) 2019 Kalycito Infotech Private Limited
30436 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
30437 */
30438
30439
30440
30441#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
30442
30443
30444#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
30445#endif
30446
30447#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
30448#endif
30449
30450#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
30451#endif
30452
30453/* This functionality of this API will be used in future to create mirror Variables - TODO */
30454/* #define UA_MAX_SIZENAME 64 */ /* Max size of Qualified Name of Subscribed Variable */
30455
30456/* Clear DataSetReader */
30457static void
30458UA_DataSetReader_clear(UA_Server *server, UA_DataSetReader *dataSetReader);
30459
30460static void
30461UA_PubSubDSRDataSetField_sampleValue(UA_Server *server, UA_DataSetReader *dataSetReader,
30462 UA_DataValue *value, UA_FieldTargetVariable *ftv) {
30463 /* TODO: Static value source without RT information model
30464 * This API supports only to external datasource in RT configutation
30465 * TODO: Extend to support other configuration if required */
30466
30467 /* Get the Node */
30468 const UA_VariableNode *rtNode = (const UA_VariableNode *)
30469 UA_NODESTORE_GET(server, &ftv->targetVariable.targetNodeId);
30470 if(!rtNode)
30471 return;
30472
30473 if(rtNode->valueBackend.backendType == UA_VALUEBACKENDTYPE_EXTERNAL) {
30474 /* Set the external source in the dataset reader config */
30475 ftv->externalDataValue = rtNode->valueBackend.backend.external.value;
30476
30477 /* Get the value to compute the offsets */
30478 *value = **rtNode->valueBackend.backend.external.value;
30479 value->value.storageType = UA_VARIANT_DATA_NODELETE;
30480 }
30481
30482 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
30483}
30484
30485static UA_StatusCode
30486UA_PubSubDataSetReader_generateKeyFrameMessage(UA_Server *server,
30487 UA_DataSetMessage *dataSetMessage,
30488 UA_DataSetReader *dataSetReader) {
30489 /* Prepare DataSetMessageContent */
30490 UA_TargetVariables *tv = &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget;
30491 dataSetMessage->header.dataSetMessageValid = true;
30492 dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
30493 dataSetMessage->data.keyFrameData.fieldCount = (UA_UInt16) tv->targetVariablesSize;
30494 dataSetMessage->data.keyFrameData.dataSetFields = (UA_DataValue *)
30495 UA_Array_new(tv->targetVariablesSize, &UA_TYPES[UA_TYPES_DATAVALUE]);
30496 if(!dataSetMessage->data.keyFrameData.dataSetFields)
30497 return UA_STATUSCODE_BADOUTOFMEMORY;
30498
30499 for(size_t counter = 0; counter < tv->targetVariablesSize; counter++) {
30500 /* Sample the value and set the source in the reader config */
30501 UA_DataValue *dfv = &dataSetMessage->data.keyFrameData.dataSetFields[counter];
30502 UA_FieldTargetVariable *ftv = &tv->targetVariables[counter];
30503 UA_PubSubDSRDataSetField_sampleValue(server, dataSetReader, dfv, ftv);
30504
30505 /* Deactivate statuscode? */
30506 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30507 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0)
30508 dfv->hasStatus = false;
30509
30510 /* Deactivate timestamps */
30511 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30512 (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0)
30513 dfv->hasSourceTimestamp = false;
30514 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30515 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0)
30516 dfv->hasSourcePicoseconds = false;
30517 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30518 (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0)
30519 dfv->hasServerTimestamp = false;
30520 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30521 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0)
30522 dfv->hasServerPicoseconds = false;
30523 }
30524
30525 return UA_STATUSCODE_GOOD;
30526}
30527
30528/* Generate a DataSetMessage for the given reader. */
30529UA_StatusCode
30530UA_DataSetReader_generateDataSetMessage(UA_Server *server,
30531 UA_DataSetMessage *dataSetMessage,
30532 UA_DataSetReader *dataSetReader) {
30533 /* Reset the message */
30534 memset(dataSetMessage, 0, sizeof(UA_DataSetMessage));
30535
30536 /* Support only for UADP configuration
30537 * TODO: JSON encoding if UA_DataSetReader_generateDataSetMessage used other
30538 * that RT configuration */
30539
30540 UA_ExtensionObject *settings = &dataSetReader->config.messageSettings;
30541 if(settings->content.decoded.type != &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]) {
30542 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30543 "Only UADP encoding is supported.");
30544 return UA_STATUSCODE_BADNOTSUPPORTED;
30545 }
30546
30547 /* The configuration Flags are included inside the std. defined UA_UadpDataSetReaderMessageDataType */
30548 UA_UadpDataSetReaderMessageDataType defaultUadpConfiguration;
30549 UA_UadpDataSetReaderMessageDataType *dataSetReaderMessageDataType =
30550 (UA_UadpDataSetReaderMessageDataType*) settings->content.decoded.data;
30551
30552 if(!(settings->encoding == UA_EXTENSIONOBJECT_DECODED ||
30553 settings->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) ||
30554 !dataSetReaderMessageDataType->dataSetMessageContentMask) {
30555 /* create default flag configuration if no dataSetMessageContentMask or even messageSettings in
30556 * UadpDataSetWriterMessageDataType was passed in */
30557 memset(&defaultUadpConfiguration, 0, sizeof(UA_UadpDataSetReaderMessageDataType));
30558 defaultUadpConfiguration.dataSetMessageContentMask = (UA_UadpDataSetMessageContentMask)
30559 ((u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP |
30560 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION |
30561 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION);
30562 dataSetReaderMessageDataType = &defaultUadpConfiguration;
30563 }
30564
30565 /* Sanity-test the configuration */
30566 if(dataSetReaderMessageDataType &&
30567 (dataSetReaderMessageDataType->networkMessageNumber != 0 ||
30568 dataSetReaderMessageDataType->dataSetOffset != 0)) {
30569 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30570 "Static DSM configuration not supported. Using defaults");
30571 dataSetReaderMessageDataType->networkMessageNumber = 0;
30572 dataSetReaderMessageDataType->dataSetOffset = 0;
30573 }
30574
30575 /* The field encoding depends on the flags inside the reader config. */
30576 if(dataSetReader->config.dataSetFieldContentMask &
30577 (u64)UA_DATASETFIELDCONTENTMASK_RAWDATA) {
30578 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
30579 } else if((u64)dataSetReader->config.dataSetFieldContentMask &
30580 ((u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP |
30581 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS |
30582 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS |
30583 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE)) {
30584 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
30585 } else {
30586 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
30587 }
30588
30589 /* Std: 'The DataSetMessageContentMask defines the flags for the content
30590 * of the DataSetMessage header.' */
30591 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30592 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION) {
30593 dataSetMessage->header.configVersionMajorVersionEnabled = true;
30594 dataSetMessage->header.configVersionMajorVersion =
30595 dataSetReader->config.dataSetMetaData.configurationVersion.majorVersion;
30596 }
30597
30598 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30599 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION) {
30600 dataSetMessage->header.configVersionMinorVersionEnabled = true;
30601 dataSetMessage->header.configVersionMinorVersion =
30602 dataSetReader->config.dataSetMetaData.configurationVersion.minorVersion;
30603 }
30604
30605 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30606 (u64)UA_UADPDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
30607 /* Will be modified when subscriber receives new nw msg */
30608 dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
30609 dataSetMessage->header.dataSetMessageSequenceNr = 1;
30610 }
30611
30612 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30613 (u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP) {
30614 dataSetMessage->header.timestampEnabled = true;
30615 dataSetMessage->header.timestamp = UA_DateTime_now();
30616 }
30617
30618 /* TODO: Picoseconds resolution not supported atm */
30619 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30620 (u64)UA_UADPDATASETMESSAGECONTENTMASK_PICOSECONDS) {
30621 dataSetMessage->header.picoSecondsIncluded = false;
30622 }
30623
30624 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30625 (u64)UA_UADPDATASETMESSAGECONTENTMASK_STATUS) {
30626 dataSetMessage->header.statusEnabled = true;
30627 }
30628
30629 /* Not supported for Delta frames atm */
30630 return UA_PubSubDataSetReader_generateKeyFrameMessage(server, dataSetMessage, dataSetReader);
30631}
30632
30633UA_StatusCode
30634UA_DataSetReader_generateNetworkMessage(UA_PubSubConnection *pubSubConnection,
30635 UA_DataSetReader *dataSetReader,
30636 UA_DataSetMessage *dsm, UA_UInt16 *writerId,
30637 UA_Byte dsmCount, UA_NetworkMessage *nm) {
30638 UA_ExtensionObject *settings = &dataSetReader->config.messageSettings;
30639 if(settings->content.decoded.type != &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE])
30640 return UA_STATUSCODE_BADNOTSUPPORTED;
30641
30642 UA_UadpDataSetReaderMessageDataType *dsrm =
30643 (UA_UadpDataSetReaderMessageDataType*)settings->content.decoded.data;
30644 nm->publisherIdEnabled = ((u64)dsrm->networkMessageContentMask &
30645 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID) != 0;
30646 nm->groupHeaderEnabled = ((u64)dsrm->networkMessageContentMask &
30647 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER) != 0;
30648 nm->groupHeader.writerGroupIdEnabled = ((u64)dsrm->networkMessageContentMask &
30649 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID) != 0;
30650 nm->groupHeader.groupVersionEnabled = ((u64)dsrm->networkMessageContentMask &
30651 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPVERSION) != 0;
30652 nm->groupHeader.networkMessageNumberEnabled = ((u64)dsrm->networkMessageContentMask &
30653 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_NETWORKMESSAGENUMBER) != 0;
30654 nm->groupHeader.sequenceNumberEnabled = ((u64)dsrm->networkMessageContentMask &
30655 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_SEQUENCENUMBER) != 0;
30656 nm->payloadHeaderEnabled = ((u64)dsrm->networkMessageContentMask &
30657 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER) != 0;
30658 nm->timestampEnabled = ((u64)dsrm->networkMessageContentMask &
30659 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_TIMESTAMP) != 0;
30660 nm->picosecondsEnabled = ((u64)dsrm->networkMessageContentMask &
30661 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PICOSECONDS) != 0;
30662 nm->dataSetClassIdEnabled = ((u64)dsrm->networkMessageContentMask &
30663 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_DATASETCLASSID) != 0;
30664 nm->promotedFieldsEnabled = ((u64)dsrm->networkMessageContentMask &
30665 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PROMOTEDFIELDS) != 0;
30666 nm->version = 1;
30667 nm->networkMessageType = UA_NETWORKMESSAGE_DATASET;
30668
30669 if(!UA_DataType_isNumeric(dataSetReader->config.publisherId.type))
30670 return UA_STATUSCODE_BADNOTSUPPORTED;
30671
30672 switch(dataSetReader->config.publisherId.type->typeKind) {
30673 case UA_DATATYPEKIND_BYTE:
30674 nm->publisherIdType = UA_PUBLISHERDATATYPE_BYTE;
30675 nm->publisherId.publisherIdByte = *(UA_Byte *) dataSetReader->config.publisherId.data;
30676 break;
30677 case UA_DATATYPEKIND_UINT16:
30678 nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT16;
30679 nm->publisherId.publisherIdUInt16 = *(UA_UInt16 *) dataSetReader->config.publisherId.data;
30680 break;
30681 case UA_DATATYPEKIND_UINT32:
30682 nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT32;
30683 nm->publisherId.publisherIdUInt32 = *(UA_UInt32 *) dataSetReader->config.publisherId.data;
30684 break;
30685 case UA_DATATYPEKIND_UINT64:
30686 nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT64;
30687 nm->publisherId.publisherIdUInt64 = *(UA_UInt64 *) dataSetReader->config.publisherId.data;
30688 break;
30689 default:
30690 return UA_STATUSCODE_BADNOTSUPPORTED;
30691 }
30692
30693 if(nm->groupHeader.sequenceNumberEnabled)
30694 nm->groupHeader.sequenceNumber = 1; /* Will be modified when subscriber receives new nw msg. */
30695
30696 if(nm->groupHeader.groupVersionEnabled)
30697 nm->groupHeader.groupVersion = dsrm->groupVersion;
30698
30699 /* Compute the length of the dsm separately for the header */
30700 UA_UInt16 *dsmLengths = (UA_UInt16 *) UA_calloc(dsmCount, sizeof(UA_UInt16));
30701 if(!dsmLengths)
30702 return UA_STATUSCODE_BADOUTOFMEMORY;
30703 for(UA_Byte i = 0; i < dsmCount; i++){
30704 dsmLengths[i] = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&dsm[i], NULL, 0);
30705 switch(dataSetReader->config.expectedEncoding) {
30706 case UA_PUBSUB_RT_UNKNOWN:
30707 break;
30708 case UA_PUBSUB_RT_VARIANT:
30709 dsm[i].header.fieldEncoding = UA_FIELDENCODING_VARIANT;
30710 break;
30711 case UA_PUBSUB_RT_DATA_VALUE:
30712 dsm[i].header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
30713 break;
30714 case UA_PUBSUB_RT_RAW:
30715 dsm[i].header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
30716 break;
30717 }
30718 }
30719 nm->payloadHeader.dataSetPayloadHeader.count = dsmCount;
30720 nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerId;
30721 nm->groupHeader.writerGroupId = dataSetReader->config.writerGroupId;
30722 nm->groupHeader.networkMessageNumber = 1; /* number of the NetworkMessage inside a PublishingInterval */
30723 nm->payload.dataSetPayload.sizes = dsmLengths;
30724 nm->payload.dataSetPayload.dataSetMessages = dsm;
30725 return UA_STATUSCODE_GOOD;
30726}
30727
30728static UA_StatusCode
30729checkReaderIdentifier(UA_Server *server, UA_NetworkMessage *msg,
30730 UA_DataSetReader *reader) {
30731 if(!msg->groupHeaderEnabled || !msg->groupHeader.writerGroupIdEnabled ||
30732 !msg->payloadHeaderEnabled) {
30733 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
30734 "Cannot process DataSetReader without WriterGroup"
30735 "and DataSetWriter identifiers");
30736 return UA_STATUSCODE_BADNOTIMPLEMENTED;
30737 }
30738
30739 switch(msg->publisherIdType) {
30740 case UA_PUBLISHERDATATYPE_BYTE:
30741 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_BYTE] &&
30742 msg->publisherIdType == UA_PUBLISHERDATATYPE_BYTE &&
30743 msg->publisherId.publisherIdByte == *(UA_Byte*)reader->config.publisherId.data)
30744 break;
30745 return UA_STATUSCODE_BADNOTFOUND;
30746 case UA_PUBLISHERDATATYPE_UINT16:
30747 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT16] &&
30748 msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT16 &&
30749 msg->publisherId.publisherIdUInt16 == *(UA_UInt16*)reader->config.publisherId.data)
30750 break;
30751 return UA_STATUSCODE_BADNOTFOUND;
30752 case UA_PUBLISHERDATATYPE_UINT32:
30753 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT32] &&
30754 msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT32 &&
30755 msg->publisherId.publisherIdUInt32 == *(UA_UInt32*)reader->config.publisherId.data)
30756 break;
30757 return UA_STATUSCODE_BADNOTFOUND;
30758 case UA_PUBLISHERDATATYPE_UINT64:
30759 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT64] &&
30760 msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT64 &&
30761 msg->publisherId.publisherIdUInt64 == *(UA_UInt64*)reader->config.publisherId.data)
30762 break;
30763 return UA_STATUSCODE_BADNOTFOUND;
30764 case UA_PUBLISHERDATATYPE_STRING:
30765 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_STRING] &&
30766 msg->publisherIdType == UA_PUBLISHERDATATYPE_STRING &&
30767 UA_String_equal(&msg->publisherId.publisherIdString,
30768 (UA_String*)reader->config.publisherId.data))
30769 break;
30770 return UA_STATUSCODE_BADNOTFOUND;
30771 default:
30772 return UA_STATUSCODE_BADNOTFOUND;
30773 }
30774
30775 if(reader->config.writerGroupId == msg->groupHeader.writerGroupId &&
30776 reader->config.dataSetWriterId == *msg->payloadHeader.dataSetPayloadHeader.dataSetWriterIds) {
30777 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
30778 "DataSetReader found. Process NetworkMessage");
30779 return UA_STATUSCODE_GOOD;
30780 }
30781
30782 return UA_STATUSCODE_BADNOTFOUND;
30783}
30784
30785UA_StatusCode
30786UA_Server_addDataSetReader(UA_Server *server, UA_NodeId readerGroupIdentifier,
30787 const UA_DataSetReaderConfig *dataSetReaderConfig,
30788 UA_NodeId *readerIdentifier) {
30789 /* Search the reader group by the given readerGroupIdentifier */
30790 UA_ReaderGroup *readerGroup = UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
30791 if(readerGroup == NULL)
30792 return UA_STATUSCODE_BADNOTFOUND;
30793
30794 if(!dataSetReaderConfig)
30795 return UA_STATUSCODE_BADNOTFOUND;
30796
30797 if(readerGroup->configurationFrozen){
30798 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30799 "Add DataSetReader failed. Subscriber configuration is frozen.");
30800 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30801 }
30802
30803 /* Allocate memory for new DataSetReader */
30804 UA_DataSetReader *newDataSetReader = (UA_DataSetReader *)
30805 UA_calloc(1, sizeof(UA_DataSetReader));
30806 if(!newDataSetReader)
30807 return UA_STATUSCODE_BADOUTOFMEMORY;
30808
30809 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
30810 newDataSetReader->componentType = UA_PUBSUB_COMPONENT_DATASETREADER;
30811 if(readerGroup->state == UA_PUBSUBSTATE_OPERATIONAL) {
30812 retVal = UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, newDataSetReader);
30813 if(retVal != UA_STATUSCODE_GOOD) {
30814 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30815 "Add DataSetReader failed. setPubSubState failed.");
30816 UA_free(newDataSetReader);
30817 newDataSetReader = 0;
30818 return retVal;
30819 }
30820 }
30821
30822 /* Copy the config into the new dataSetReader */
30823 UA_DataSetReaderConfig_copy(dataSetReaderConfig, &newDataSetReader->config);
30824 newDataSetReader->linkedReaderGroup = readerGroup->identifier;
30825
30826#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
30827 retVal = addDataSetReaderRepresentation(server, newDataSetReader);
30828 if(retVal != UA_STATUSCODE_GOOD) {
30829 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30830 "Add DataSetReader failed. addDataSetReaderRepresentation failed.");
30831 UA_DataSetReaderConfig_clear(&newDataSetReader->config);
30832 UA_free(newDataSetReader);
30833 newDataSetReader = 0;
30834 return retVal;
30835 }
30836#else
30837 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
30838 &newDataSetReader->identifier);
30839#endif
30840
30841#ifdef UA_ENABLE_PUBSUB_MONITORING
30842 /* create message receive timeout timer */
30843 retVal = server->config.pubSubConfig.monitoringInterface.createMonitoring(
30844 server,
30845 newDataSetReader->identifier,
30846 UA_PUBSUB_COMPONENT_DATASETREADER,
30847 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT,
30848 newDataSetReader,
30849 UA_DataSetReader_handleMessageReceiveTimeout);
30850 if(retVal != UA_STATUSCODE_GOOD) {
30851 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30852 "Add DataSetReader failed. Create message receive timeout timer failed.");
30853 UA_DataSetReaderConfig_clear(&newDataSetReader->config);
30854 UA_free(newDataSetReader);
30855 newDataSetReader = 0;
30856 return retVal;
30857 }
30858#endif /* UA_ENABLE_PUBSUB_MONITORING */
30859
30860 /* Add the new reader to the group */
30861 LIST_INSERT_HEAD(&readerGroup->readers, newDataSetReader, listEntry);
30862 readerGroup->readersCount++;
30863
30864 if(readerIdentifier)
30865 UA_NodeId_copy(&newDataSetReader->identifier, readerIdentifier);
30866
30867 return retVal;
30868}
30869
30870UA_StatusCode
30871UA_Server_removeDataSetReader(UA_Server *server, UA_NodeId readerIdentifier) {
30872 /* Remove datasetreader given by the identifier */
30873 UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, readerIdentifier);
30874 if(!dsr)
30875 return UA_STATUSCODE_BADNOTFOUND;
30876
30877 if(dsr->configurationFrozen) {
30878 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30879 "Remove DataSetReader failed. "
30880 "Subscriber configuration is frozen.");
30881 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30882 }
30883
30884#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
30885 removeDataSetReaderRepresentation(server, dsr);
30886#endif
30887
30888 UA_StatusCode res = UA_STATUSCODE_GOOD;
30889#ifdef UA_ENABLE_PUBSUB_MONITORING
30890 /* Stop and remove message receive timeout timer */
30891 if(dsr->msgRcvTimeoutTimerRunning) {
30892 res = server->config.pubSubConfig.monitoringInterface.
30893 stopMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
30894 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
30895 if(res != UA_STATUSCODE_GOOD) {
30896 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30897 "Remove DataSetReader failed. Stop message "
30898 "receive timeout timer of DataSetReader '%.*s' failed.",
30899 (int) dsr->config.name.length, dsr->config.name.data);
30900 }
30901 }
30902
30903 res |= server->config.pubSubConfig.monitoringInterface.
30904 deleteMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
30905 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
30906 if(res != UA_STATUSCODE_GOOD) {
30907 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30908 "Remove DataSetReader failed. Delete message receive "
30909 "timeout timer of DataSetReader '%.*s' failed.",
30910 (int) dsr->config.name.length, dsr->config.name.data);
30911 }
30912#endif /* UA_ENABLE_PUBSUB_MONITORING */
30913
30914 UA_DataSetReader_clear(server, dsr);
30915 return res;
30916}
30917
30918UA_StatusCode
30919UA_Server_DataSetReader_updateConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
30920 UA_NodeId readerGroupIdentifier,
30921 const UA_DataSetReaderConfig *config) {
30922 if(config == NULL)
30923 return UA_STATUSCODE_BADINVALIDARGUMENT;
30924
30925 UA_DataSetReader *currentDataSetReader =
30926 UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
30927 if(!currentDataSetReader)
30928 return UA_STATUSCODE_BADNOTFOUND;
30929
30930 if(currentDataSetReader->configurationFrozen){
30931 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30932 "Update DataSetReader config failed. "
30933 "Subscriber configuration is frozen.");
30934 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30935 }
30936
30937 UA_ReaderGroup *currentReaderGroup =
30938 UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
30939 if(currentReaderGroup->configurationFrozen) {
30940 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30941 "Update DataSetReader config failed. "
30942 "Subscriber configuration is frozen.");
30943 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30944 }
30945
30946 /* The update functionality will be extended during the next PubSub batches.
30947 * Currently changes for writerGroupId, dataSetWriterId and TargetVariables are possible. */
30948 if(currentDataSetReader->config.writerGroupId != config->writerGroupId)
30949 currentDataSetReader->config.writerGroupId = config->writerGroupId;
30950
30951 if(currentDataSetReader->config.dataSetWriterId != config->dataSetWriterId)
30952 currentDataSetReader->config.dataSetWriterId = config->dataSetWriterId;
30953
30954 if(currentDataSetReader->config.subscribedDataSetType != UA_PUBSUB_SDS_TARGET) {
30955 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30956 "Unsupported SubscribedDataSetType.");
30957 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30958 }
30959
30960 UA_TargetVariables *oldTV =
30961 &currentDataSetReader->config.subscribedDataSet.subscribedDataSetTarget;
30962 const UA_TargetVariables *newTV =
30963 &config->subscribedDataSet.subscribedDataSetTarget;
30964 if(oldTV->targetVariablesSize == newTV->targetVariablesSize) {
30965 for(size_t i = 0; i < config->subscribedDataSet.subscribedDataSetTarget.targetVariablesSize; i++) {
30966 if(!UA_NodeId_equal(&oldTV->targetVariables[i].targetVariable.targetNodeId,
30967 &newTV->targetVariables[i].targetVariable.targetNodeId)) {
30968 UA_Server_DataSetReader_createTargetVariables(server, currentDataSetReader->identifier,
30969 newTV->targetVariablesSize, newTV->targetVariables);
30970 }
30971 }
30972 } else {
30973 UA_Server_DataSetReader_createTargetVariables(server, currentDataSetReader->identifier,
30974 newTV->targetVariablesSize, newTV->targetVariables);
30975 }
30976
30977 UA_StatusCode res = UA_STATUSCODE_GOOD;
30978#ifdef UA_ENABLE_PUBSUB_MONITORING
30979 if(currentDataSetReader->config.messageReceiveTimeout != config->messageReceiveTimeout) {
30980 /* Update message receive timeout timer interval */
30981 currentDataSetReader->config.messageReceiveTimeout = config->messageReceiveTimeout;
30982 res = server->config.pubSubConfig.monitoringInterface.
30983 updateMonitoringInterval(server, currentDataSetReader->identifier,
30984 UA_PUBSUB_COMPONENT_DATASETREADER,
30985 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT,
30986 currentDataSetReader);
30987 if(res != UA_STATUSCODE_GOOD) {
30988 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30989 "Update DataSetReader message receive timeout timer failed.");
30990 }
30991 }
30992#endif /* UA_ENABLE_PUBSUB_MONITORING */
30993 return res;
30994}
30995
30996UA_StatusCode
30997UA_Server_DataSetReader_getConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
30998 UA_DataSetReaderConfig *config) {
30999 if(!config)
31000 return UA_STATUSCODE_BADINVALIDARGUMENT;
31001
31002 UA_DataSetReader *currentDataSetReader =
31003 UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
31004 if(!currentDataSetReader)
31005 return UA_STATUSCODE_BADNOTFOUND;
31006
31007 UA_DataSetReaderConfig tmpReaderConfig;
31008 /* Deep copy of the actual config */
31009 UA_DataSetReaderConfig_copy(&currentDataSetReader->config, &tmpReaderConfig);
31010 *config = tmpReaderConfig;
31011 return UA_STATUSCODE_GOOD;
31012}
31013
31014UA_StatusCode
31015UA_DataSetReaderConfig_copy(const UA_DataSetReaderConfig *src,
31016 UA_DataSetReaderConfig *dst) {
31017 memset(dst, 0, sizeof(UA_DataSetReaderConfig));
31018 UA_StatusCode retVal = UA_String_copy(&src->name, &dst->name);
31019 if(retVal != UA_STATUSCODE_GOOD)
31020 return retVal;
31021
31022 retVal = UA_Variant_copy(&src->publisherId, &dst->publisherId);
31023 if(retVal != UA_STATUSCODE_GOOD)
31024 return retVal;
31025
31026 dst->writerGroupId = src->writerGroupId;
31027 dst->dataSetWriterId = src->dataSetWriterId;
31028 dst->expectedEncoding = src->expectedEncoding;
31029 retVal = UA_DataSetMetaDataType_copy(&src->dataSetMetaData, &dst->dataSetMetaData);
31030 if(retVal != UA_STATUSCODE_GOOD)
31031 return retVal;
31032
31033 dst->dataSetFieldContentMask = src->dataSetFieldContentMask;
31034 dst->messageReceiveTimeout = src->messageReceiveTimeout;
31035
31036 /* Currently memcpy is used to copy the securityParameters */
31037 memcpy(&dst->securityParameters, &src->securityParameters, sizeof(UA_PubSubSecurityParameters));
31038 retVal = UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
31039 if(retVal != UA_STATUSCODE_GOOD)
31040 return retVal;
31041
31042 retVal = UA_ExtensionObject_copy(&src->transportSettings, &dst->transportSettings);
31043 if(retVal != UA_STATUSCODE_GOOD)
31044 return retVal;
31045
31046 if(src->subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
31047 retVal = UA_TargetVariables_copy(&src->subscribedDataSet.subscribedDataSetTarget,
31048 &dst->subscribedDataSet.subscribedDataSetTarget);
31049 }
31050 return retVal;
31051}
31052
31053void
31054UA_DataSetReaderConfig_clear(UA_DataSetReaderConfig *cfg) {
31055 UA_String_clear(&cfg->name);
31056 UA_Variant_clear(&cfg->publisherId);
31057 UA_DataSetMetaDataType_clear(&cfg->dataSetMetaData);
31058 UA_ExtensionObject_clear(&cfg->messageSettings);
31059 UA_ExtensionObject_clear(&cfg->transportSettings);
31060 if(cfg->subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
31061 UA_TargetVariables_clear(&cfg->subscribedDataSet.subscribedDataSetTarget);
31062 }
31063}
31064
31065UA_StatusCode
31066UA_Server_DataSetReader_getState(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
31067 UA_PubSubState *state) {
31068
31069 if((server == NULL) || (state == NULL))
31070 return UA_STATUSCODE_BADINVALIDARGUMENT;
31071 UA_DataSetReader *currentDataSetReader =
31072 UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
31073 if(currentDataSetReader == NULL)
31074 return UA_STATUSCODE_BADNOTFOUND;
31075 *state = currentDataSetReader->state;
31076 return UA_STATUSCODE_GOOD;
31077}
31078
31079static UA_StatusCode
31080UA_DataSetReader_setState_disabled(UA_Server *server, UA_DataSetReader *dsr) {
31081 UA_StatusCode ret = UA_STATUSCODE_GOOD;
31082 switch(dsr->state) {
31083 case UA_PUBSUBSTATE_DISABLED:
31084 return UA_STATUSCODE_GOOD;
31085 case UA_PUBSUBSTATE_PAUSED:
31086 dsr->state = UA_PUBSUBSTATE_DISABLED;
31087 return UA_STATUSCODE_GOOD;
31088 case UA_PUBSUBSTATE_OPERATIONAL:
31089#ifdef UA_ENABLE_PUBSUB_MONITORING
31090 /* Stop MessageReceiveTimeout timer */
31091 if(dsr->msgRcvTimeoutTimerRunning == UA_TRUE) {
31092 ret = server->config.pubSubConfig.monitoringInterface.
31093 stopMonitoring(server, dsr->identifier,
31094 UA_PUBSUB_COMPONENT_DATASETREADER,
31095 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
31096 if(ret == UA_STATUSCODE_GOOD) {
31097 dsr->msgRcvTimeoutTimerRunning = UA_FALSE;
31098 } else {
31099 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31100 "Disable ReaderGroup failed. Stop message receive "
31101 "timeout timer of DataSetReader '%.*s' failed.",
31102 (int) dsr->config.name.length, dsr->config.name.data);
31103 }
31104 }
31105#endif /* UA_ENABLE_PUBSUB_MONITORING */
31106 if(ret == UA_STATUSCODE_GOOD)
31107 dsr->state = UA_PUBSUBSTATE_DISABLED;
31108 return ret;
31109 case UA_PUBSUBSTATE_ERROR:
31110 break;
31111 default:
31112 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31113 "Received unknown PubSub state!");
31114 }
31115 return UA_STATUSCODE_BADINVALIDARGUMENT;
31116}
31117
31118/* State machine methods not part of the open62541 state machine API */
31119UA_StatusCode
31120UA_DataSetReader_setPubSubState(UA_Server *server, UA_PubSubState state,
31121 UA_DataSetReader *dataSetReader) {
31122 switch(state) {
31123 case UA_PUBSUBSTATE_DISABLED:
31124 return UA_DataSetReader_setState_disabled(server, dataSetReader);
31125 case UA_PUBSUBSTATE_PAUSED:
31126 return UA_STATUSCODE_BADNOTSUPPORTED;
31127 case UA_PUBSUBSTATE_OPERATIONAL:
31128 dataSetReader->state = UA_PUBSUBSTATE_OPERATIONAL;
31129 break;
31130 case UA_PUBSUBSTATE_ERROR:
31131 dataSetReader->state = UA_PUBSUBSTATE_ERROR;
31132 break;
31133 default:
31134 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31135 "Received unknown PubSub state!");
31136 return UA_STATUSCODE_BADINVALIDARGUMENT;
31137 }
31138 return UA_STATUSCODE_GOOD;
31139}
31140
31141UA_StatusCode
31142UA_FieldTargetVariable_copy(const UA_FieldTargetVariable *src, UA_FieldTargetVariable *dst) {
31143 /* Do a simple memcpy */
31144 memcpy(dst, src, sizeof(UA_FieldTargetVariable));
31145 return UA_FieldTargetDataType_copy(&src->targetVariable, &dst->targetVariable);
31146}
31147
31148UA_StatusCode
31149UA_TargetVariables_copy(const UA_TargetVariables *src, UA_TargetVariables *dst) {
31150 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
31151 memcpy(dst, src, sizeof(UA_TargetVariables));
31152 if(src->targetVariablesSize > 0) {
31153 dst->targetVariables = (UA_FieldTargetVariable*)
31154 UA_calloc(src->targetVariablesSize, sizeof(UA_FieldTargetVariable));
31155 if(!dst->targetVariables)
31156 return UA_STATUSCODE_BADOUTOFMEMORY;
31157 for(size_t i = 0; i < src->targetVariablesSize; i++)
31158 retVal |= UA_FieldTargetVariable_copy(&src->targetVariables[i], &dst->targetVariables[i]);
31159 }
31160 return retVal;
31161}
31162
31163void
31164UA_TargetVariables_clear(UA_TargetVariables *subscribedDataSetTarget) {
31165 for(size_t i = 0; i < subscribedDataSetTarget->targetVariablesSize; i++) {
31166 UA_FieldTargetDataType_clear(&subscribedDataSetTarget->targetVariables[i].targetVariable);
31167 }
31168 if(subscribedDataSetTarget->targetVariablesSize > 0)
31169 UA_free(subscribedDataSetTarget->targetVariables);
31170 memset(subscribedDataSetTarget, 0, sizeof(UA_TargetVariables));
31171}
31172
31173/* This Method is used to initially set the SubscribedDataSet to
31174 * TargetVariablesType and to create the list of target Variables of a
31175 * SubscribedDataSetType. */
31176UA_StatusCode
31177UA_Server_DataSetReader_createTargetVariables(UA_Server *server,
31178 UA_NodeId dataSetReaderIdentifier,
31179 size_t targetVariablesSize,
31180 const UA_FieldTargetVariable *targetVariables) {
31181 UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
31182 if(!dataSetReader)
31183 return UA_STATUSCODE_BADINVALIDARGUMENT;
31184
31185 if(dataSetReader->configurationFrozen) {
31186 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31187 "Create Target Variables failed. Subscriber configuration is frozen.");
31188 return UA_STATUSCODE_BADCONFIGURATIONERROR;
31189 }
31190
31191 if(dataSetReader->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize > 0)
31192 UA_TargetVariables_clear(&dataSetReader->config.subscribedDataSet.subscribedDataSetTarget);
31193
31194 /* Set subscribed dataset to TargetVariableType */
31195 dataSetReader->config.subscribedDataSetType = UA_PUBSUB_SDS_TARGET;
31196 UA_TargetVariables tmp;
31197 tmp.targetVariablesSize = targetVariablesSize;
31198 tmp.targetVariables = (UA_FieldTargetVariable*)(uintptr_t)targetVariables;
31199 return UA_TargetVariables_copy(&tmp, &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget);
31200}
31201
31202/* This functionality of this API will be used in future to create mirror Variables - TODO */
31203/* UA_StatusCode
31204UA_Server_DataSetReader_createDataSetMirror(UA_Server *server, UA_String *parentObjectNodeName,
31205 UA_NodeId dataSetReaderIdentifier) {
31206 if((server == NULL) || (parentNode == NULL)) {
31207 return UA_STATUSCODE_BADINVALIDARGUMENT;
31208 }
31209
31210 UA_StatusCode retval = UA_STATUSCODE_GOOD;
31211 UA_DataSetReader* pDataSetReader = UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
31212 if(pDataSetReader == NULL) {
31213 return UA_STATUSCODE_BADINVALIDARGUMENT;
31214 }
31215
31216 if(pDataSetReader->configurationFrozen) {
31217 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31218 "Add Target Variables failed. Subscriber configuration is frozen.");
31219 return UA_STATUSCODE_BADCONFIGURATIONERROR;
31220 } // TODO: Frozen configuration variable in TargetVariable structure
31221
31222 UA_TargetVariables targetVars;
31223 targetVars.targetVariablesSize = pDataSetReader->config.dataSetMetaData.fieldsSize;
31224 targetVars.targetVariables = (UA_FieldTargetVariable *)
31225 UA_calloc(targetVars.targetVariablesSize, sizeof(UA_FieldTargetVariable));
31226
31227 for(size_t i = 0; i < pDataSetReader->config.dataSetMetaData.fieldsSize; i++) {
31228 UA_VariableAttributes vAttr = UA_VariableAttributes_default;
31229 vAttr.valueRank = pDataSetReader->config.dataSetMetaData.fields[i].valueRank;
31230 if(pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize > 0) {
31231 retval = UA_Array_copy(pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensions,
31232 pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize,
31233 (void**)&vAttr.arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]);
31234 if(retval == UA_STATUSCODE_GOOD) {
31235 vAttr.arrayDimensionsSize =
31236 pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize;
31237 }
31238
31239 }
31240
31241 vAttr.dataType = pDataSetReader->config.dataSetMetaData.fields[i].dataType;
31242
31243 vAttr.accessLevel = UA_ACCESSLEVELMASK_READ;
31244 UA_LocalizedText_copy(&pDataSetReader->config.dataSetMetaData.fields[i].description,
31245 &vAttr.description);
31246 UA_QualifiedName qn;
31247 UA_QualifiedName_init(&qn);
31248 char szTmpName[UA_MAX_SIZENAME];
31249 if(pDataSetReader->config.dataSetMetaData.fields[i].name.length > 0) {
31250 UA_UInt16 slen = UA_MAX_SIZENAME -1;
31251 vAttr.displayName.locale = UA_STRING("en-US");
31252 vAttr.displayName.text = pDataSetReader->config.dataSetMetaData.fields[i].name;
31253 if(pDataSetReader->config.dataSetMetaData.fields[i].name.length < slen) {
31254 slen = (UA_UInt16)pDataSetReader->config.dataSetMetaData.fields[i].name.length;
31255 UA_snprintf(szTmpName, sizeof(szTmpName), "%.*s", (int)slen,
31256 (const char*)pDataSetReader->config.dataSetMetaData.fields[i].name.data);
31257 }
31258
31259 szTmpName[slen] = '\0';
31260 qn = UA_QUALIFIEDNAME(1, szTmpName);
31261 }
31262 else {
31263 strcpy(szTmpName, "SubscribedVariable");
31264 vAttr.displayName = UA_LOCALIZEDTEXT("en-US", szTmpName);
31265 qn = UA_QUALIFIEDNAME(1, "SubscribedVariable");
31266 }
31267
31268 // Add variable to the given parent node
31269 UA_NodeId newNode;
31270 retval = UA_Server_addVariableNode(server, UA_NODEID_NULL, *parentNode,
31271 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), qn,
31272 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
31273 vAttr, NULL, &newNode);
31274 if(retval == UA_STATUSCODE_GOOD) {
31275 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
31276 "addVariableNode %s succeeded", szTmpName);
31277 }
31278 else {
31279 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
31280 "addVariableNode: error 0x%" PRIx32, retval);
31281 }
31282
31283 targetVars.targetVariables[i].targetVariable.attributeId = UA_ATTRIBUTEID_VALUE;
31284 UA_NodeId_copy(&newNode, &targetVars.targetVariables[i].targetVariable.targetNodeId);
31285 UA_NodeId_clear(&newNode);
31286 if(vAttr.arrayDimensionsSize > 0) {
31287 UA_Array_delete(vAttr.arrayDimensions, vAttr.arrayDimensionsSize,
31288 &UA_TYPES[UA_TYPES_UINT32]);
31289 }
31290 }
31291
31292 UA_TargetVariables_clear(&targetVars);
31293 return retval;
31294}*/
31295
31296static void
31297DataSetReader_processRaw(UA_Server *server, UA_ReaderGroup *rg,
31298 UA_DataSetReader *dsr, UA_DataSetMessage* msg) {
31299 UA_LOG_TRACE(&server->config.logger, UA_LOGCATEGORY_SERVER,
31300 "Received RAW Frame");
31301 msg->data.keyFrameData.fieldCount = (UA_UInt16)
31302 dsr->config.dataSetMetaData.fieldsSize;
31303
31304 size_t offset = 0;
31305 for(size_t i = 0; i < dsr->config.dataSetMetaData.fieldsSize; i++) {
31306 /* TODO The datatype reference should be part of the internal
31307 * pubsub configuration to avoid the time-expensive lookup */
31308 const UA_DataType *type =
31309 UA_findDataTypeWithCustom(&dsr->config.dataSetMetaData.fields[i].dataType,
31310 server->config.customDataTypes);
31311 msg->data.keyFrameData.rawFields.length += type->memSize;
31312 UA_STACKARRAY(UA_Byte, value, type->memSize);
31313 UA_StatusCode res =
31314 UA_decodeBinaryInternal(&msg->data.keyFrameData.rawFields,
31315 &offset, value, type, NULL);
31316 if(res != UA_STATUSCODE_GOOD) {
31317 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31318 "Error during Raw-decode KeyFrame field %u: %s",
31319 (unsigned)i, UA_StatusCode_name(res));
31320 return;
31321 }
31322
31323 UA_FieldTargetVariable *tv =
31324 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
31325
31326 if(rg->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
31327 if (tv->beforeWrite) {
31328 void *pData = (**tv->externalDataValue).value.data;
31329 (**tv->externalDataValue).value.data = value; // set raw data as "preview"
31330 tv->beforeWrite(server,
31331 &dsr->identifier,
31332 &dsr->linkedReaderGroup,
31333 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariable.targetNodeId,
31334 dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariableContext,
31335 tv->externalDataValue);
31336 (**tv->externalDataValue).value.data = pData; // restore previous data pointer
31337 }
31338 memcpy((**tv->externalDataValue).value.data, value, type->memSize);
31339 if(tv->afterWrite)
31340 tv->afterWrite(server, &dsr->identifier,
31341 &dsr->linkedReaderGroup,
31342 &tv->targetVariable.targetNodeId,
31343 tv->targetVariableContext,
31344 tv->externalDataValue);
31345 continue; /* No dynamic allocation for fixed-size msg, no need to _clear */
31346 }
31347
31348 UA_WriteValue writeVal;
31349 UA_WriteValue_init(&writeVal);
31350 writeVal.attributeId = tv->targetVariable.attributeId;
31351 writeVal.indexRange = tv->targetVariable.receiverIndexRange;
31352 writeVal.nodeId = tv->targetVariable.targetNodeId;
31353 UA_Variant_setScalar(&writeVal.value.value, value, type);
31354 writeVal.value.hasValue = true;
31355 res = UA_Server_write(server, &writeVal);
31356 UA_clear(value, type);
31357 if(res != UA_STATUSCODE_GOOD) {
31358 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31359 "Error writing KeyFrame field %u: %s",
31360 (unsigned)i, UA_StatusCode_name(res));
31361 }
31362 }
31363}
31364
31365static void
31366DataSetReader_processFixedSize(UA_Server *server, UA_ReaderGroup *rg,
31367 UA_DataSetReader *dsr, UA_DataSetMessage *msg,
31368 size_t fieldCount) {
31369 for(size_t i = 0; i < fieldCount; i++) {
31370 if(!msg->data.keyFrameData.dataSetFields[i].hasValue)
31371 continue;
31372
31373 UA_FieldTargetVariable *tv =
31374 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
31375 if(tv->targetVariable.attributeId != UA_ATTRIBUTEID_VALUE)
31376 continue;
31377 if (tv->beforeWrite) {
31378 UA_DataValue *tmp = &msg->data.keyFrameData.dataSetFields[i];
31379 tv->beforeWrite(server,
31380 &dsr->identifier,
31381 &dsr->linkedReaderGroup,
31382 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariable.targetNodeId,
31383 dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariableContext,
31384 &tmp);
31385 }
31386 memcpy((**tv->externalDataValue).value.data,
31387 msg->data.keyFrameData.dataSetFields[i].value.data,
31388 msg->data.keyFrameData.dataSetFields[i].value.type->memSize);
31389 if(tv->afterWrite)
31390 tv->afterWrite(server, &dsr->identifier, &dsr->linkedReaderGroup,
31391 &tv->targetVariable.targetNodeId,
31392 tv->targetVariableContext, tv->externalDataValue);
31393 }
31394}
31395
31396void
31397UA_DataSetReader_process(UA_Server *server, UA_ReaderGroup *rg,
31398 UA_DataSetReader *dsr, UA_DataSetMessage *msg) {
31399 if(!dsr || !rg || !msg || !server)
31400 return;
31401
31402 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
31403 "DataSetReader '%.*s': received a network message",
31404 (int) dsr->config.name.length, dsr->config.name.data);
31405
31406 if(!msg->header.dataSetMessageValid) {
31407 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31408 "DataSetMessage is discarded: message is not valid");
31409 /* To Do check ConfigurationVersion */
31410 /* if(msg->header.configVersionMajorVersionEnabled) {
31411 * if(msg->header.configVersionMajorVersion !=
31412 * dsr->config.dataSetMetaData.configurationVersion.majorVersion) {
31413 * UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
31414 * "DataSetMessage is discarded: ConfigurationVersion "
31415 * "MajorVersion does not match");
31416 * return;
31417 * }
31418 * } */
31419 return;
31420 }
31421
31422 if(msg->header.dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME) {
31423 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31424 "DataSetMessage is discarded: Only keyframes are supported");
31425 return;
31426 }
31427
31428 /* Process message with raw encoding (realtime and non-realtime) */
31429 if(msg->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
31430 DataSetReader_processRaw(server, rg, dsr, msg);
31431#ifdef UA_ENABLE_PUBSUB_MONITORING
31432 UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
31433#endif
31434 return;
31435 }
31436
31437 /* Check and adjust the field count
31438 * TODO Throw an error if non-matching? */
31439 size_t fieldCount = msg->data.keyFrameData.fieldCount;
31440 if(dsr->config.dataSetMetaData.fieldsSize < fieldCount)
31441 fieldCount = dsr->config.dataSetMetaData.fieldsSize;
31442
31443 if(dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize < fieldCount)
31444 fieldCount = dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize;
31445
31446 /* Process message with fixed size fields (realtime capable) */
31447 if(rg->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
31448 DataSetReader_processFixedSize(server, rg, dsr, msg, fieldCount);
31449#ifdef UA_ENABLE_PUBSUB_MONITORING
31450 UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
31451#endif
31452 return;
31453 }
31454
31455 /* Write the message fields via the write service (non realtime) */
31456 UA_StatusCode res = UA_STATUSCODE_GOOD;
31457 for(size_t i = 0; i < fieldCount; i++) {
31458 if(!msg->data.keyFrameData.dataSetFields[i].hasValue)
31459 continue;
31460
31461 UA_FieldTargetVariable *tv =
31462 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
31463
31464 UA_WriteValue writeVal;
31465 UA_WriteValue_init(&writeVal);
31466 writeVal.attributeId = tv->targetVariable.attributeId;
31467 writeVal.indexRange = tv->targetVariable.receiverIndexRange;
31468 writeVal.nodeId = tv->targetVariable.targetNodeId;
31469 writeVal.value = msg->data.keyFrameData.dataSetFields[i];
31470 res = UA_Server_write(server, &writeVal);
31471 if(res != UA_STATUSCODE_GOOD)
31472 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31473 "Error writing KeyFrame field %u: %s",
31474 (unsigned)i, UA_StatusCode_name(res));
31475 }
31476
31477#ifdef UA_ENABLE_PUBSUB_MONITORING
31478 UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
31479#endif
31480}
31481
31482#ifdef UA_ENABLE_PUBSUB_MONITORING
31483
31484void
31485UA_DataSetReader_checkMessageReceiveTimeout(UA_Server *server,
31486 UA_DataSetReader *dsr) {
31487 UA_assert(server != 0);
31488 UA_assert(dsr != 0);
31489
31490 /* If previous reader state was error (because we haven't received messages
31491 * and ran into timeout) we should set the state back to operational */
31492 if(dsr->state == UA_PUBSUBSTATE_ERROR) {
31493 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, dsr);
31494 if(server->config.pubSubConfig.stateChangeCallback != 0) {
31495 server->config.pubSubConfig.stateChangeCallback(&dsr->identifier,
31496 UA_PUBSUBSTATE_OPERATIONAL,
31497 UA_STATUSCODE_GOOD);
31498 }
31499 }
31500
31501 /* Stop message receive timeout timer */
31502 UA_StatusCode res;
31503 if(dsr->msgRcvTimeoutTimerRunning) {
31504 res = server->config.pubSubConfig.monitoringInterface.
31505 stopMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
31506 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
31507 if(res == UA_STATUSCODE_GOOD) {
31508 dsr->msgRcvTimeoutTimerRunning = false;
31509 } else {
31510 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31511 "DataSetReader '%.*s': stop receive timeout timer failed",
31512 (int)dsr->config.name.length, dsr->config.name.data);
31513 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
31514 }
31515 }
31516
31517 /* Start message receive timeout timer */
31518 res = server->config.pubSubConfig.monitoringInterface.
31519 startMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
31520 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
31521 if(res == UA_STATUSCODE_GOOD) {
31522 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
31523 "Info: DataSetReader '%.*s': start receive timeout timer",
31524 (int)dsr->config.name.length, dsr->config.name.data);
31525 dsr->msgRcvTimeoutTimerRunning = true;
31526 } else {
31527 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31528 "Starting Message Receive Timeout timer failed.");
31529 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
31530 }
31531}
31532
31533/* Timeout callback for DataSetReader MessageReceiveTimeout handling */
31534void
31535UA_DataSetReader_handleMessageReceiveTimeout(UA_Server *server,
31536 void *dataSetReader) {
31537 if(!server || !dataSetReader) {
31538 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31539 "UA_DataSetReader_handleMessageReceiveTimeout(): "
31540 "null pointer param");
31541 return;
31542 }
31543
31544 UA_DataSetReader *dsr = (UA_DataSetReader*) dataSetReader;
31545 if(dsr->componentType != UA_PUBSUB_COMPONENT_DATASETREADER) {
31546 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31547 "UA_DataSetReader_handleMessageReceiveTimeout(): "
31548 "input param is not of type DataSetReader");
31549 return;
31550 }
31551
31552 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
31553 "UA_DataSetReader_handleMessageReceiveTimeout(): "
31554 "MessageReceiveTimeout occurred at DataSetReader "
31555 "'%.*s': MessageReceiveTimeout = %f Timer Id = %u ",
31556 (int)dsr->config.name.length, dsr->config.name.data,
31557 dsr->config.messageReceiveTimeout,
31558 (UA_UInt32) dsr->msgRcvTimeoutTimerId);
31559
31560 UA_ServerConfig *pConfig = UA_Server_getConfig(server);
31561 if(pConfig->pubSubConfig.stateChangeCallback != 0) {
31562 pConfig->pubSubConfig.stateChangeCallback(&dsr->identifier,
31563 UA_PUBSUBSTATE_ERROR,
31564 UA_STATUSCODE_BADTIMEOUT);
31565 }
31566
31567 UA_StatusCode res =
31568 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
31569 if(res != UA_STATUSCODE_GOOD) {
31570 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31571 "UA_DataSetReader_handleMessageReceiveTimeout(): "
31572 "setting pubsub state failed");
31573 }
31574}
31575#endif /* UA_ENABLE_PUBSUB_MONITORING */
31576
31577static void
31578UA_DataSetReader_clear(UA_Server *server, UA_DataSetReader *dsr) {
31579 /* Delete DataSetReader config */
31580 UA_DataSetReaderConfig_clear(&dsr->config);
31581
31582 /* Delete DataSetReader */
31583 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, dsr->linkedReaderGroup);
31584 if(rg)
31585 rg->readersCount--;
31586
31587 UA_NodeId_clear(&dsr->identifier);
31588 UA_NodeId_clear(&dsr->linkedReaderGroup);
31589 if(dsr->config.subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
31590 UA_TargetVariables_clear(&dsr->config.subscribedDataSet.subscribedDataSetTarget);
31591 } else {
31592 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31593 "UA_DataSetReader_clear(): unsupported subscribed dataset enum type");
31594 }
31595
31596 /* Remove DataSetReader from group */
31597 LIST_REMOVE(dsr, listEntry);
31598
31599 /* Free memory allocated for DataSetReader */
31600 UA_free(dsr);
31601}
31602
31603static void
31604processMessageWithReader(UA_Server *server, UA_ReaderGroup *readerGroup,
31605 UA_DataSetReader *reader, UA_NetworkMessage *msg) {
31606 UA_Byte totalDataSets = 1;
31607 if(msg->payloadHeaderEnabled)
31608 totalDataSets = msg->payloadHeader.dataSetPayloadHeader.count;
31609 for(UA_Byte i = 0; i < totalDataSets; i++) {
31610 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
31611 "Process Msg with DataSetReader!");
31612 UA_DataSetReader_process(server, readerGroup, reader,
31613 &msg->payload.dataSetPayload.dataSetMessages[i]);
31614 }
31615}
31616
31617UA_StatusCode
31618UA_Server_processNetworkMessage(UA_Server *server, UA_PubSubConnection *connection,
31619 UA_NetworkMessage* msg) {
31620 if(!msg || !connection)
31621 return UA_STATUSCODE_BADINVALIDARGUMENT;
31622
31623 /* To Do The condition pMsg->dataSetClassIdEnabled
31624 * Here some filtering is possible */
31625
31626 if(!msg->publisherIdEnabled) {
31627 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31628 "Cannot process DataSetReader without PublisherId");
31629 return UA_STATUSCODE_BADNOTIMPLEMENTED; /* TODO: Handle DSR without PublisherId */
31630 }
31631
31632 /* There can be several readers listening for the same network message */
31633 UA_Boolean processed = false;
31634 UA_ReaderGroup *readerGroup;
31635 UA_DataSetReader *reader;
31636 LIST_FOREACH(readerGroup, &connection->readerGroups, listEntry) {
31637 LIST_FOREACH(reader, &readerGroup->readers, listEntry) {
31638 UA_StatusCode retval = checkReaderIdentifier(server, msg, reader);
31639 if(retval == UA_STATUSCODE_GOOD) {
31640 processed = true;
31641 processMessageWithReader(server, readerGroup, reader, msg);
31642 }
31643 }
31644 }
31645
31646 if(!processed) {
31647 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31648 "Dataset reader not found. Check PublisherID, WriterGroupID "
31649 "and DatasetWriterID");
31650 }
31651
31652 return UA_STATUSCODE_GOOD;
31653}
31654
31655/********************************************************************************
31656 * Functionality related to decoding, decrypting and processing network messages
31657 * as a subscriber
31658 ********************************************************************************/
31659
31660#define MIN_PAYLOAD_SIZE_ETHERNET 46
31661
31662/* Delete the payload value of every decoded DataSet field */
31663static void UA_DataSetMessage_freeDecodedPayload(UA_DataSetMessage *dsm) {
31664 if(dsm->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
31665 for(size_t i = 0; i < dsm->data.keyFrameData.fieldCount; i++) {
31666#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
31667 UA_Variant_init(&dsm->data.keyFrameData.dataSetFields[i].value);
31668#else
31669 UA_Variant_clear(&dsm->data.keyFrameData.dataSetFields[i].value);
31670#endif
31671 }
31672 }
31673 else if(dsm->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
31674 for(size_t i = 0; i < dsm->data.keyFrameData.fieldCount; i++) {
31675#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
31676 UA_DataValue_init(&dsm->data.keyFrameData.dataSetFields[i]);
31677#else
31678 UA_DataValue_clear(&dsm->data.keyFrameData.dataSetFields[i]);
31679#endif
31680 }
31681 }
31682}
31683
31684UA_StatusCode
31685decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos,
31686 UA_NetworkMessage *nm, UA_PubSubConnection *connection) {
31687#ifdef UA_DEBUG_DUMP_PKGS
31688 UA_dump_hex_pkg(buffer->data, buffer->length);
31689#endif
31690
31691 UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(buffer, pos, nm);
31692 UA_CHECK_STATUS_ERROR(rv, return rv,
31693 &server->config.logger, UA_LOGCATEGORY_SERVER,
31694 "PubSub receive. decoding headers failed");
31695
31696#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
31697 UA_Boolean processed = false;
31698 UA_ReaderGroup *readerGroup;
31699 UA_DataSetReader *reader;
31700
31701 /* Choose a correct readergroup for decrypt/verify this message
31702 * (there could be multiple) */
31703 LIST_FOREACH(readerGroup, &connection->readerGroups, listEntry) {
31704 LIST_FOREACH(reader, &readerGroup->readers, listEntry) {
31705 UA_StatusCode retval = checkReaderIdentifier(server, nm, reader);
31706 if(retval == UA_STATUSCODE_GOOD) {
31707 processed = true;
31708 rv = verifyAndDecryptNetworkMessage(&server->config.logger, buffer, pos,
31709 nm, readerGroup);
31710 UA_CHECK_STATUS_WARN(rv, return rv,
31711 &server->config.logger, UA_LOGCATEGORY_SERVER,
31712 "Subscribe failed. verify and decrypt network message failed.");
31713
31714#ifdef UA_DEBUG_DUMP_PKGS
31715 UA_dump_hex_pkg(buffer->data, buffer->length);
31716#endif
31717 /* break out of all loops when first verify & decrypt was successful */
31718 goto loops_exit;
31719 }
31720 }
31721 }
31722
31723loops_exit:
31724 if(!processed) {
31725 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31726 "Dataset reader not found. Check PublisherId, "
31727 "WriterGroupId and DatasetWriterId");
31728 /* Possible multicast scenario: there are multiple connections (with one
31729 * or more ReaderGroups) within a multicast group every connection
31730 * receives all network messages, even if some of them are not meant for
31731 * the connection currently processed -> therefore it is ok if the
31732 * connection does not have a DataSetReader for every received network
31733 * message. We must not return an error here, but continue with the
31734 * buffer decoding and see if we have a matching DataSetReader for the
31735 * next network message. */
31736 }
31737#endif
31738
31739 rv = UA_NetworkMessage_decodePayload(buffer, pos, nm);
31740 UA_CHECK_STATUS(rv, return rv);
31741
31742 rv = UA_NetworkMessage_decodeFooters(buffer, pos, nm);
31743 UA_CHECK_STATUS(rv, return rv);
31744
31745 return UA_STATUSCODE_GOOD;
31746}
31747
31748static
31749UA_StatusCode
31750decodeAndProcessNetworkMessage(UA_Server *server, UA_ReaderGroup *readerGroup,
31751 UA_PubSubConnection *connection,
31752 UA_ByteString *buffer) {
31753 UA_NetworkMessage nm;
31754 memset(&nm, 0, sizeof(UA_NetworkMessage));
31755 size_t currentPosition = 0;
31756
31757 UA_StatusCode rv = UA_STATUSCODE_GOOD;
31758 rv = decodeNetworkMessage(server, buffer, &currentPosition, &nm, connection);
31759 UA_CHECK_STATUS_WARN(rv, goto cleanup, &server->config.logger, UA_LOGCATEGORY_SERVER,
31760 "Subscribe failed. verify, decrypt and decode network message failed.");
31761
31762 rv = UA_Server_processNetworkMessage(server, connection, &nm);
31763 // TODO: check what action to perform on error (nothing?)
31764 UA_CHECK_STATUS_WARN(rv, (void)0, &server->config.logger, UA_LOGCATEGORY_SERVER,
31765 "Subscribe failed. process network message failed.");
31766
31767cleanup:
31768 UA_NetworkMessage_clear(&nm);
31769 return rv;
31770}
31771
31772static
31773UA_StatusCode
31774decodeAndProcessNetworkMessageRT(UA_Server *server, UA_ReaderGroup *readerGroup,
31775 UA_PubSubConnection *connection,
31776 UA_ByteString *buffer) {
31777#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
31778 useMembufAlloc();
31779#endif
31780
31781 /* Considering max DSM as 1
31782 * TODO: Process with the static value source */
31783 size_t currentPosition = 0;
31784 UA_DataSetReader *dataSetReader = LIST_FIRST(&readerGroup->readers);
31785 UA_NetworkMessage *nm = dataSetReader->bufferedMessage.nm;
31786
31787 /* Decode only the necessary offset and update the networkMessage */
31788 UA_StatusCode res =
31789 UA_NetworkMessage_updateBufferedNwMessage(&dataSetReader->bufferedMessage,
31790 buffer, &currentPosition);
31791 if(res != UA_STATUSCODE_GOOD) {
31792 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31793 "PubSub receive. Unknown field type.");
31794 res = UA_STATUSCODE_UNCERTAIN;
31795 goto cleanup;
31796 }
31797
31798 /* Check the decoded message is the expected one
31799 * TODO: PublisherID check after modification in NM to support all datatypes */
31800 if(nm->groupHeader.writerGroupId != dataSetReader->config.writerGroupId ||
31801 *nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != dataSetReader->config.dataSetWriterId) {
31802 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31803 "PubSub receive. Unknown message received. Will not be processed.");
31804 res = UA_STATUSCODE_UNCERTAIN;
31805 goto cleanup;
31806 }
31807
31808 UA_DataSetReader_process(server, readerGroup, dataSetReader,
31809 nm->payload.dataSetPayload.dataSetMessages);
31810
31811 cleanup:
31812 UA_DataSetMessage_freeDecodedPayload(nm->payload.dataSetPayload.dataSetMessages);
31813#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
31814 useNormalAlloc();
31815#endif
31816 return res;
31817}
31818
31819typedef struct {
31820 UA_Server *server;
31821 UA_PubSubConnection *connection;
31822 UA_ReaderGroup *readerGroup;
31823} UA_RGContext;
31824
31825static UA_StatusCode
31826decodeAndProcessFun(UA_PubSubChannel *channel, void *cbContext,
31827 const UA_ByteString *buffer) {
31828 UA_ByteString mutableBuffer = {buffer->length, buffer->data};
31829 UA_RGContext *ctx = (UA_RGContext*) cbContext;
31830 return decodeAndProcessNetworkMessage(ctx->server, ctx->readerGroup,
31831 ctx->connection, &mutableBuffer);
31832}
31833
31834static UA_StatusCode
31835decodeAndProcessFunRT(UA_PubSubChannel *channel, void *cbContext,
31836 const UA_ByteString *buffer) {
31837 UA_ByteString mutableBuffer = {buffer->length, buffer->data};
31838 UA_RGContext *ctx = (UA_RGContext*) cbContext;
31839 return decodeAndProcessNetworkMessageRT(ctx->server, ctx->readerGroup,
31840 ctx->connection, &mutableBuffer);
31841}
31842
31843UA_StatusCode
31844receiveBufferedNetworkMessage(UA_Server *server, UA_ReaderGroup *readerGroup,
31845 UA_PubSubConnection *connection) {
31846 UA_RGContext ctx = {server, connection, readerGroup};
31847 UA_PubSubReceiveCallback receiveCB;
31848 if(readerGroup->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE)
31849 receiveCB = decodeAndProcessFunRT;
31850 else
31851 receiveCB = decodeAndProcessFun;
31852
31853 /* TODO: Move the TransportSettings to to the readerGroupConfig. So we can
31854 * use it here instead of a NULL pointer. */
31855 UA_StatusCode rv =
31856 connection->channel->receive(connection->channel, NULL,
31857 receiveCB, &ctx,
31858 readerGroup->config.timeout);
31859
31860 // TODO attention: here rv is ok if UA_STATUSCODE_GOOD != rv
31861 UA_CHECK_WARN(!UA_StatusCode_isBad(rv), return rv,
31862 &server->config.logger, UA_LOGCATEGORY_SERVER,
31863 "SubscribeCallback(): Connection receive failed!");
31864
31865 return UA_STATUSCODE_GOOD;
31866}
31867
31868#endif /* UA_ENABLE_PUBSUB */
31869
31870/**** amalgamated original file "/src/pubsub/ua_pubsub_readergroup.c" ****/
31871
31872/* This Source Code Form is subject to the terms of the Mozilla Public
31873 * License, v. 2.0. If a copy of the MPL was not distributed with this
31874 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
31875 *
31876 * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
31877 * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
31878 * Copyright (c) 2019 Kalycito Infotech Private Limited
31879 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
31880 */
31881
31882
31883
31884#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
31885
31886
31887#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
31888#endif
31889
31890UA_ReaderGroup *
31891UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier) {
31892 UA_PubSubConnection *pubSubConnection;
31893 TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
31894 UA_ReaderGroup* readerGroup = NULL;
31895 LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) {
31896 if(UA_NodeId_equal(&identifier, &readerGroup->identifier))
31897 return readerGroup;
31898 }
31899 }
31900 return NULL;
31901}
31902
31903UA_DataSetReader *UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier) {
31904 UA_PubSubConnection *pubSubConnection;
31905 TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
31906 UA_ReaderGroup* readerGroup = NULL;
31907 LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) {
31908 UA_DataSetReader *tmpReader;
31909 LIST_FOREACH(tmpReader, &readerGroup->readers, listEntry) {
31910 if(UA_NodeId_equal(&tmpReader->identifier, &identifier))
31911 return tmpReader;
31912 }
31913 }
31914 }
31915 return NULL;
31916}
31917
31918/* Clear ReaderGroup */
31919static void
31920UA_Server_ReaderGroup_clear(UA_Server* server, UA_ReaderGroup *readerGroup);
31921
31922/* ReaderGroup Config Handling */
31923
31924UA_StatusCode
31925UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src,
31926 UA_ReaderGroupConfig *dst) {
31927 memcpy(dst, src, sizeof(UA_ReaderGroupConfig));
31928
31929 UA_StatusCode res = UA_String_copy(&src->name, &dst->name);
31930 if(res != UA_STATUSCODE_GOOD)
31931 return res;
31932
31933 res = UA_Array_copy(src->groupProperties, src->groupPropertiesSize,
31934 (void**)&dst->groupProperties,
31935 &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
31936 if(res != UA_STATUSCODE_GOOD) {
31937 UA_String_clear(&dst->name);
31938 return res;
31939 }
31940 dst->groupPropertiesSize = src->groupPropertiesSize;
31941 return UA_STATUSCODE_GOOD;
31942}
31943
31944void
31945UA_ReaderGroupConfig_clear(UA_ReaderGroupConfig *readerGroupConfig) {
31946 UA_String_clear(&readerGroupConfig->name);
31947 UA_Array_delete(readerGroupConfig->groupProperties,
31948 readerGroupConfig->groupPropertiesSize,
31949 &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
31950 readerGroupConfig->groupProperties = NULL;
31951 readerGroupConfig->groupPropertiesSize = 0;
31952}
31953
31954/* ReaderGroup Lifecycle */
31955
31956UA_StatusCode
31957UA_Server_addReaderGroup(UA_Server *server, UA_NodeId connectionIdentifier,
31958 const UA_ReaderGroupConfig *readerGroupConfig,
31959 UA_NodeId *readerGroupIdentifier) {
31960 UA_StatusCode retval = UA_STATUSCODE_GOOD;
31961
31962 /* Check for valid readergroup configuration */
31963 if(!readerGroupConfig)
31964 return UA_STATUSCODE_BADINVALIDARGUMENT;
31965
31966 if(!readerGroupConfig->pubsubManagerCallback.addCustomCallback &&
31967 readerGroupConfig->enableBlockingSocket) {
31968 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31969 "Adding ReaderGroup failed, blocking socket functionality "
31970 "only supported in customcallback");
31971 return UA_STATUSCODE_BADNOTSUPPORTED;
31972 }
31973
31974 /* Search the connection by the given connectionIdentifier */
31975 UA_PubSubConnection *currentConnectionContext =
31976 UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier);
31977 if(!currentConnectionContext)
31978 return UA_STATUSCODE_BADNOTFOUND;
31979
31980 if(currentConnectionContext->configurationFrozen){
31981 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31982 "Adding ReaderGroup failed. Subscriber configuration is frozen.");
31983 return UA_STATUSCODE_BADCONFIGURATIONERROR;
31984 }
31985
31986 /* Regist (bind) the connection channel if it is not already registered */
31987 if(!currentConnectionContext->isRegistered) {
31988 retval |= UA_PubSubConnection_regist(server, &connectionIdentifier);
31989 if(retval != UA_STATUSCODE_GOOD)
31990 return retval;
31991 }
31992
31993 /* Allocate memory for new reader group */
31994 UA_ReaderGroup *newGroup = (UA_ReaderGroup *)UA_calloc(1, sizeof(UA_ReaderGroup));
31995 if(!newGroup)
31996 return UA_STATUSCODE_BADOUTOFMEMORY;
31997
31998 newGroup->componentType = UA_PUBSUB_COMPONENT_READERGROUP;
31999 /* Generate nodeid for the readergroup identifier */
32000 newGroup->linkedConnection = currentConnectionContext->identifier;
32001
32002 /* Deep copy of the config */
32003 retval |= UA_ReaderGroupConfig_copy(readerGroupConfig, &newGroup->config);
32004 /* Check user configured params and define it accordingly */
32005 if(newGroup->config.subscribingInterval <= 0.0)
32006 newGroup->config.subscribingInterval = 5; // Set default to 5 ms
32007
32008 if(newGroup->config.enableBlockingSocket)
32009 newGroup->config.timeout = 0; // Set timeout to 0 for blocking socket
32010
32011 if((!newGroup->config.enableBlockingSocket) && (!newGroup->config.timeout))
32012 newGroup->config.timeout = 1000; /* Set default to 1ms socket timeout
32013 when non-blocking socket allows with
32014 zero timeout */
32015
32016 LIST_INSERT_HEAD(&currentConnectionContext->readerGroups, newGroup, listEntry);
32017 currentConnectionContext->readerGroupsSize++;
32018
32019#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32020 retval |= addReaderGroupRepresentation(server, newGroup);
32021#else
32022 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
32023 &newGroup->identifier);
32024#endif
32025 if(readerGroupIdentifier)
32026 UA_NodeId_copy(&newGroup->identifier, readerGroupIdentifier);
32027
32028 return retval;
32029}
32030
32031UA_StatusCode
32032UA_Server_removeReaderGroup(UA_Server *server, UA_NodeId groupIdentifier) {
32033 UA_ReaderGroup* readerGroup =
32034 UA_ReaderGroup_findRGbyId(server, groupIdentifier);
32035 if(readerGroup == NULL)
32036 return UA_STATUSCODE_BADNOTFOUND;
32037
32038 if(readerGroup->configurationFrozen){
32039 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32040 "Remove ReaderGroup failed. Subscriber configuration is frozen.");
32041 return UA_STATUSCODE_BADCONFIGURATIONERROR;
32042 }
32043
32044 /* Search the connection to which the given readergroup is connected to */
32045 UA_PubSubConnection *connection =
32046 UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
32047 if(connection == NULL)
32048 return UA_STATUSCODE_BADNOTFOUND;
32049
32050 /* Unregister subscribe callback */
32051 if(readerGroup->state == UA_PUBSUBSTATE_OPERATIONAL)
32052 UA_ReaderGroup_removeSubscribeCallback(server, readerGroup);
32053
32054#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32055 removeReaderGroupRepresentation(server, readerGroup);
32056#endif
32057
32058 /* UA_Server_ReaderGroup_clear also removes itself from the list */
32059 UA_Server_ReaderGroup_clear(server, readerGroup);
32060
32061 /* Remove readerGroup from Connection */
32062 LIST_REMOVE(readerGroup, listEntry);
32063 UA_free(readerGroup);
32064 return UA_STATUSCODE_GOOD;
32065}
32066
32067/* TODO: Implement
32068UA_StatusCode
32069UA_Server_ReaderGroup_updateConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
32070 const UA_ReaderGroupConfig *config) {
32071 return UA_STATUSCODE_BADNOTIMPLEMENTED;
32072}
32073*/
32074
32075UA_StatusCode
32076UA_Server_ReaderGroup_getConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
32077 UA_ReaderGroupConfig *config) {
32078 if(!config)
32079 return UA_STATUSCODE_BADINVALIDARGUMENT;
32080
32081 /* Identify the readergroup through the readerGroupIdentifier */
32082 UA_ReaderGroup *currentReaderGroup =
32083 UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
32084 if(!currentReaderGroup)
32085 return UA_STATUSCODE_BADNOTFOUND;
32086
32087 UA_ReaderGroupConfig tmpReaderGroupConfig;
32088 /* deep copy of the actual config */
32089 UA_ReaderGroupConfig_copy(&currentReaderGroup->config, &tmpReaderGroupConfig);
32090 *config = tmpReaderGroupConfig;
32091 return UA_STATUSCODE_GOOD;
32092}
32093
32094static void
32095UA_Server_ReaderGroup_clear(UA_Server* server, UA_ReaderGroup *readerGroup) {
32096 UA_ReaderGroupConfig_clear(&readerGroup->config);
32097 UA_DataSetReader *dataSetReader;
32098 UA_DataSetReader *tmpDataSetReader;
32099 LIST_FOREACH_SAFE(dataSetReader, &readerGroup->readers, listEntry, tmpDataSetReader) {
32100 UA_Server_removeDataSetReader(server, dataSetReader->identifier);
32101 }
32102 UA_PubSubConnection* pConn =
32103 UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
32104 if(pConn != NULL)
32105 pConn->readerGroupsSize--;
32106
32107 /* Delete ReaderGroup and its members */
32108 UA_NodeId_clear(&readerGroup->linkedConnection);
32109 UA_NodeId_clear(&readerGroup->identifier);
32110
32111#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
32112 if(readerGroup->config.securityPolicy && readerGroup->securityPolicyContext) {
32113 readerGroup->config.securityPolicy->deleteContext(readerGroup->securityPolicyContext);
32114 readerGroup->securityPolicyContext = NULL;
32115 }
32116#endif
32117
32118 UA_ReaderGroupConfig_clear(&readerGroup->config);
32119}
32120
32121UA_StatusCode
32122UA_Server_ReaderGroup_getState(UA_Server *server, UA_NodeId readerGroupIdentifier,
32123 UA_PubSubState *state) {
32124 if((server == NULL) || (state == NULL))
32125 return UA_STATUSCODE_BADINVALIDARGUMENT;
32126 UA_ReaderGroup *currentReaderGroup =
32127 UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
32128 if(!currentReaderGroup)
32129 return UA_STATUSCODE_BADNOTFOUND;
32130 *state = currentReaderGroup->state;
32131 return UA_STATUSCODE_GOOD;
32132}
32133
32134/* ReaderGroup State */
32135
32136static UA_StatusCode
32137UA_ReaderGroup_setPubSubState_disable(UA_Server *server,
32138 UA_ReaderGroup *rg) {
32139 UA_DataSetReader *dataSetReader;
32140 switch(rg->state) {
32141 case UA_PUBSUBSTATE_DISABLED:
32142 return UA_STATUSCODE_GOOD;
32143 case UA_PUBSUBSTATE_PAUSED:
32144 break;
32145 case UA_PUBSUBSTATE_OPERATIONAL:
32146 UA_ReaderGroup_removeSubscribeCallback(server, rg);
32147 LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
32148 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_DISABLED,
32149 dataSetReader);
32150 }
32151 rg->state = UA_PUBSUBSTATE_DISABLED;
32152 break;
32153 case UA_PUBSUBSTATE_ERROR:
32154 break;
32155 default:
32156 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32157 "Unknown PubSub state!");
32158 return UA_STATUSCODE_BADINTERNALERROR;
32159 }
32160 return UA_STATUSCODE_GOOD;
32161}
32162
32163static UA_StatusCode
32164UA_ReaderGroup_setPubSubState_paused(UA_Server *server,
32165 UA_ReaderGroup *rg) {
32166 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
32167 "PubSub state paused is unsupported at the moment!");
32168 switch(rg->state) {
32169 case UA_PUBSUBSTATE_DISABLED:
32170 break;
32171 case UA_PUBSUBSTATE_PAUSED:
32172 return UA_STATUSCODE_GOOD;
32173 case UA_PUBSUBSTATE_OPERATIONAL:
32174 break;
32175 case UA_PUBSUBSTATE_ERROR:
32176 break;
32177 default:
32178 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32179 "Unknown PubSub state!");
32180 return UA_STATUSCODE_BADINTERNALERROR;
32181 }
32182 return UA_STATUSCODE_BADNOTSUPPORTED;
32183}
32184
32185static UA_StatusCode
32186UA_ReaderGroup_setPubSubState_operational(UA_Server *server,
32187 UA_ReaderGroup *rg) {
32188 UA_DataSetReader *dataSetReader;
32189 switch(rg->state) {
32190 case UA_PUBSUBSTATE_DISABLED:
32191 LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
32192 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, dataSetReader);
32193 }
32194 UA_ReaderGroup_addSubscribeCallback(server, rg);
32195 rg->state = UA_PUBSUBSTATE_OPERATIONAL;
32196 return UA_STATUSCODE_GOOD;
32197 case UA_PUBSUBSTATE_PAUSED:
32198 break;
32199 case UA_PUBSUBSTATE_OPERATIONAL:
32200 return UA_STATUSCODE_GOOD;
32201 case UA_PUBSUBSTATE_ERROR:
32202 break;
32203 default:
32204 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32205 "Unknown PubSub state!");
32206 return UA_STATUSCODE_BADINTERNALERROR;
32207 }
32208 return UA_STATUSCODE_BADNOTSUPPORTED;
32209}
32210
32211static UA_StatusCode
32212UA_ReaderGroup_setPubSubState_error(UA_Server *server,
32213 UA_ReaderGroup *rg) {
32214 UA_DataSetReader *dataSetReader;
32215 switch(rg->state) {
32216 case UA_PUBSUBSTATE_DISABLED:
32217 break;
32218 case UA_PUBSUBSTATE_PAUSED:
32219 break;
32220 case UA_PUBSUBSTATE_OPERATIONAL:
32221 UA_ReaderGroup_removeSubscribeCallback(server, rg);
32222 LIST_FOREACH(dataSetReader, &rg->readers, listEntry){
32223 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dataSetReader);
32224 }
32225 break;
32226 case UA_PUBSUBSTATE_ERROR:
32227 return UA_STATUSCODE_GOOD;
32228 default:
32229 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32230 "Unknown PubSub state!");
32231 return UA_STATUSCODE_BADINTERNALERROR;
32232 }
32233 rg->state = UA_PUBSUBSTATE_ERROR;
32234 return UA_STATUSCODE_GOOD;
32235}
32236
32237UA_StatusCode
32238UA_ReaderGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
32239 UA_ReaderGroup *readerGroup) {
32240 switch(state) {
32241 case UA_PUBSUBSTATE_DISABLED:
32242 return UA_ReaderGroup_setPubSubState_disable(server, readerGroup);
32243 case UA_PUBSUBSTATE_PAUSED:
32244 return UA_ReaderGroup_setPubSubState_paused(server, readerGroup);
32245 case UA_PUBSUBSTATE_OPERATIONAL:
32246 return UA_ReaderGroup_setPubSubState_operational(server, readerGroup);
32247 case UA_PUBSUBSTATE_ERROR:
32248 return UA_ReaderGroup_setPubSubState_error(server, readerGroup);
32249 default:
32250 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32251 "Received unknown PubSub state!");
32252 break;
32253 }
32254 return UA_STATUSCODE_BADINVALIDARGUMENT;
32255}
32256
32257UA_StatusCode
32258UA_Server_setReaderGroupOperational(UA_Server *server, const UA_NodeId readerGroupId){
32259 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
32260 if(!rg)
32261 return UA_STATUSCODE_BADNOTFOUND;
32262 return UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, rg);
32263}
32264
32265UA_StatusCode
32266UA_Server_setReaderGroupDisabled(UA_Server *server, const UA_NodeId readerGroupId){
32267 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
32268 if(!rg)
32269 return UA_STATUSCODE_BADNOTFOUND;
32270 return UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, rg);
32271}
32272
32273#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
32274UA_StatusCode
32275UA_Server_setReaderGroupEncryptionKeys(UA_Server *server, const UA_NodeId readerGroup,
32276 UA_UInt32 securityTokenId,
32277 const UA_ByteString signingKey,
32278 const UA_ByteString encryptingKey,
32279 const UA_ByteString keyNonce) {
32280 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroup);
32281 UA_CHECK_MEM(rg, return UA_STATUSCODE_BADNOTFOUND);
32282
32283 UA_CHECK_MEM_WARN(rg->config.securityPolicy, return UA_STATUSCODE_BADINTERNALERROR,
32284 &server->config.logger, UA_LOGCATEGORY_SERVER,
32285 "No SecurityPolicy configured for the ReaderGroup");
32286
32287 if(securityTokenId != rg->securityTokenId) {
32288 rg->securityTokenId = securityTokenId;
32289 rg->nonceSequenceNumber = 1;
32290 }
32291
32292 /* Create a new context */
32293 if(!rg->securityPolicyContext) {
32294 return rg->config.securityPolicy->
32295 newContext(rg->config.securityPolicy->policyContext,
32296 &signingKey, &encryptingKey, &keyNonce,
32297 &rg->securityPolicyContext);
32298 }
32299
32300 /* Update the context */
32301 return rg->config.securityPolicy->
32302 setSecurityKeys(rg->securityPolicyContext, &signingKey,
32303 &encryptingKey, &keyNonce);
32304}
32305#endif
32306
32307/* Freezing of the configuration */
32308
32309UA_StatusCode
32310UA_Server_freezeReaderGroupConfiguration(UA_Server *server,
32311 const UA_NodeId readerGroupId) {
32312 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
32313 if(!rg)
32314 return UA_STATUSCODE_BADNOTFOUND;
32315
32316 /* PubSubConnection freezeCounter++ */
32317 UA_NodeId pubSubConnectionId = rg->linkedConnection;
32318 UA_PubSubConnection *pubSubConnection =
32319 UA_PubSubConnection_findConnectionbyId(server, pubSubConnectionId);
32320 pubSubConnection->configurationFreezeCounter++;
32321 pubSubConnection->configurationFrozen = UA_TRUE;
32322
32323 /* ReaderGroup freeze */
32324 /* TODO: Clarify on the freeze functionality in multiple DSR, multiple
32325 * networkMessage conf in a RG */
32326 rg->configurationFrozen = UA_TRUE;
32327
32328 /* DataSetReader freeze */
32329 UA_DataSetReader *dataSetReader;
32330 UA_UInt16 dsrCount = 0;
32331 LIST_FOREACH(dataSetReader, &rg->readers, listEntry){
32332 dataSetReader->configurationFrozen = UA_TRUE;
32333 dsrCount++;
32334 /* TODO: Configuration frozen for subscribedDataSet once
32335 * UA_Server_DataSetReader_addTargetVariables API modified to support
32336 * adding target variable one by one or in a group stored in a list. */
32337 }
32338
32339 /* Not rt, we don't have to adjust anything */
32340 if(rg->config.rtLevel != UA_PUBSUB_RT_FIXED_SIZE)
32341 return UA_STATUSCODE_GOOD;
32342
32343 if(dsrCount > 1) {
32344 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32345 "Mutiple DSR in a readerGroup not supported in RT "
32346 "fixed size configuration");
32347 return UA_STATUSCODE_BADNOTIMPLEMENTED;
32348 }
32349
32350 dataSetReader = LIST_FIRST(&rg->readers);
32351
32352 /* Support only to UADP encoding */
32353 if(dataSetReader->config.messageSettings.content.decoded.type !=
32354 &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]) {
32355 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32356 "PubSub-RT configuration fail: Non-RT capable encoding.");
32357 return UA_STATUSCODE_BADNOTSUPPORTED;
32358 }
32359
32360 size_t fieldsSize = dataSetReader->config.dataSetMetaData.fieldsSize;
32361 for(size_t i = 0; i < fieldsSize; i++) {
32362 UA_FieldTargetVariable *tv =
32363 &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
32364 const UA_VariableNode *rtNode = (const UA_VariableNode *)
32365 UA_NODESTORE_GET(server, &tv->targetVariable.targetNodeId);
32366 if(rtNode != NULL &&
32367 rtNode->valueBackend.backendType != UA_VALUEBACKENDTYPE_EXTERNAL) {
32368 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32369 "PubSub-RT configuration fail: PDS contains field "
32370 "without external data source.");
32371 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
32372 return UA_STATUSCODE_BADNOTSUPPORTED;
32373 }
32374
32375 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
32376
32377 UA_FieldMetaData *field = &dataSetReader->config.dataSetMetaData.fields[i];
32378 if((UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_STRING].typeId) ||
32379 UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) &&
32380 field->maxStringLength == 0) {
32381 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32382 "PubSub-RT configuration fail: "
32383 "PDS contains String/ByteString with dynamic length.");
32384 return UA_STATUSCODE_BADNOTSUPPORTED;
32385 } else if(!UA_DataType_isNumeric(UA_findDataType(&field->dataType)) &&
32386 !UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_BOOLEAN].typeId)) {
32387 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32388 "PubSub-RT configuration fail: "
32389 "PDS contains variable with dynamic size.");
32390 return UA_STATUSCODE_BADNOTSUPPORTED;
32391 }
32392 }
32393
32394 UA_DataSetMessage *dsm = (UA_DataSetMessage *) UA_calloc(1, sizeof(UA_DataSetMessage));
32395 if(!dsm) {
32396 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32397 "PubSub RT Offset calculation: DSM creation failed");
32398 return UA_STATUSCODE_BADOUTOFMEMORY;
32399 }
32400
32401 /* Generate the DSM */
32402 UA_StatusCode res = UA_DataSetReader_generateDataSetMessage(server, dsm, dataSetReader);
32403 if(res != UA_STATUSCODE_GOOD) {
32404 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32405 "PubSub RT Offset calculation: DataSetMessage generation failed");
32406 UA_DataSetMessage_clear(dsm);
32407 UA_free(dsm);
32408 return UA_STATUSCODE_BADINTERNALERROR;
32409 }
32410
32411 /* Generate data set messages - Considering 1 DSM as max */
32412 UA_UInt16 *dsWriterIds = (UA_UInt16 *)UA_calloc(1, sizeof(UA_UInt16));
32413 if(!dsWriterIds) {
32414 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32415 "PubSub RT Offset calculation: DataSetWriterId creation failed");
32416 UA_DataSetMessage_clear(dsm);
32417 UA_free(dsm);
32418 return UA_STATUSCODE_BADOUTOFMEMORY;
32419 }
32420 *dsWriterIds = dataSetReader->config.dataSetWriterId;
32421
32422 UA_NetworkMessage *networkMessage = (UA_NetworkMessage *)UA_calloc(1, sizeof(UA_NetworkMessage));
32423 if(!networkMessage) {
32424 UA_free(dsWriterIds);
32425 UA_DataSetMessage_clear(dsm);
32426 UA_free(dsm);
32427 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32428 "PubSub RT Offset calculation: Network message creation failed");
32429 return UA_STATUSCODE_BADOUTOFMEMORY;
32430 }
32431
32432 res = UA_DataSetReader_generateNetworkMessage(pubSubConnection, dataSetReader, dsm,
32433 dsWriterIds, 1, networkMessage);
32434 if(res != UA_STATUSCODE_GOOD) {
32435 UA_free(networkMessage->payload.dataSetPayload.sizes);
32436 UA_free(networkMessage);
32437 UA_free(dsWriterIds);
32438 UA_DataSetMessage_clear(dsm);
32439 UA_free(dsm);
32440 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32441 "PubSub RT Offset calculation: NetworkMessage generation failed");
32442 return UA_STATUSCODE_BADINTERNALERROR;
32443 }
32444
32445 /* Fix the offsets necessary to decode */
32446 memset(&dataSetReader->bufferedMessage, 0, sizeof(UA_NetworkMessageOffsetBuffer));
32447 UA_NetworkMessage_calcSizeBinary(networkMessage, &dataSetReader->bufferedMessage);
32448 dataSetReader->bufferedMessage.RTsubscriberEnabled = true;
32449 dataSetReader->bufferedMessage.nm = networkMessage;
32450
32451 return UA_STATUSCODE_GOOD;
32452}
32453
32454UA_StatusCode
32455UA_Server_unfreezeReaderGroupConfiguration(UA_Server *server,
32456 const UA_NodeId readerGroupId) {
32457 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
32458 if(!rg)
32459 return UA_STATUSCODE_BADNOTFOUND;
32460
32461 /* PubSubConnection freezeCounter-- */
32462 UA_NodeId pubSubConnectionId = rg->linkedConnection;
32463 UA_PubSubConnection *pubSubConnection =
32464 UA_PubSubConnection_findConnectionbyId(server, pubSubConnectionId);
32465 pubSubConnection->configurationFreezeCounter--;
32466 if(pubSubConnection->configurationFreezeCounter == 0){
32467 pubSubConnection->configurationFrozen = UA_FALSE;
32468 }
32469
32470 /* ReaderGroup unfreeze */
32471 rg->configurationFrozen = UA_FALSE;
32472
32473 /* DataSetReader unfreeze */
32474 UA_DataSetReader *dataSetReader;
32475 LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
32476 UA_NetworkMessageOffsetBuffer_clear(&dataSetReader->bufferedMessage);
32477 dataSetReader->configurationFrozen = false;
32478 }
32479
32480 return UA_STATUSCODE_GOOD;
32481}
32482
32483/* This triggers the collection and reception of NetworkMessages and the
32484 * contained DataSetMessages. */
32485void
32486UA_ReaderGroup_subscribeCallback(UA_Server *server,
32487 UA_ReaderGroup *readerGroup) {
32488 // TODO: feedback for debug-assert vs runtime-check
32489 UA_assert(server);
32490 UA_assert(readerGroup);
32491
32492 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
32493 "PubSub subscribe callback");
32494
32495 UA_PubSubConnection *connection =
32496 UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
32497 if(!connection) {
32498 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32499 "SubscribeCallback(): Find linked connection failed");
32500 UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, readerGroup);
32501 return;
32502 }
32503
32504 receiveBufferedNetworkMessage(server, readerGroup, connection);
32505}
32506
32507/* Add new subscribeCallback. The first execution is triggered directly after
32508 * creation. */
32509UA_StatusCode
32510UA_ReaderGroup_addSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup) {
32511 UA_StatusCode retval = UA_STATUSCODE_GOOD;
32512 if(readerGroup->config.pubsubManagerCallback.addCustomCallback)
32513 retval = readerGroup->config.pubsubManagerCallback.
32514 addCustomCallback(server, readerGroup->identifier,
32515 (UA_ServerCallback)UA_ReaderGroup_subscribeCallback,
32516 readerGroup, readerGroup->config.subscribingInterval,
32517 NULL, // TODO: Send base time from reader group config
32518 // TODO: Send timer policy from reader group config
32519 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
32520 &readerGroup->subscribeCallbackId);
32521 else {
32522 if(readerGroup->config.enableBlockingSocket == UA_TRUE) {
32523 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32524 "addSubscribeCallback() failed, blocking socket "
32525 "functionality only supported in customcallback");
32526 return UA_STATUSCODE_BADNOTSUPPORTED;
32527 }
32528
32529 retval = UA_PubSubManager_addRepeatedCallback(server,
32530 (UA_ServerCallback)UA_ReaderGroup_subscribeCallback,
32531 readerGroup, readerGroup->config.subscribingInterval,
32532 NULL, // TODO: Send base time from reader group config
32533 // TODO: Send timer policy from reader group config
32534 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
32535 &readerGroup->subscribeCallbackId);
32536 }
32537
32538 /* Run once after creation */
32539 /* When using blocking socket functionality, the server mechanism might get
32540 * blocked. It is highly recommended to use custom callback when using
32541 * blockingsocket. */
32542 if(readerGroup->config.enableBlockingSocket != UA_TRUE)
32543 UA_ReaderGroup_subscribeCallback(server, readerGroup);
32544
32545 return retval;
32546}
32547
32548void
32549UA_ReaderGroup_removeSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup) {
32550 if(readerGroup->config.pubsubManagerCallback.removeCustomCallback)
32551 readerGroup->config.pubsubManagerCallback.
32552 removeCustomCallback(server, readerGroup->identifier,
32553 readerGroup->subscribeCallbackId);
32554 else
32555 UA_PubSubManager_removeRepeatedPubSubCallback(server,
32556 readerGroup->subscribeCallbackId);
32557}
32558
32559#endif /* UA_ENABLE_PUBSUB */
32560
32561/**** amalgamated original file "/src/pubsub/ua_pubsub_manager.c" ****/
32562
32563/* This Source Code Form is subject to the terms of the Mozilla Public
32564 * License, v. 2.0. If a copy of the MPL was not distributed with this
32565 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
32566 *
32567 * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
32568 * Copyright (c) 2018 Fraunhofer IOSB (Author: Julius Pfrommer)
32569 */
32570
32571
32572#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
32573
32574
32575#define UA_DATETIMESTAMP_2000 125911584000000000
32576
32577UA_StatusCode
32578UA_Server_addPubSubConnection(UA_Server *server,
32579 const UA_PubSubConnectionConfig *connectionConfig,
32580 UA_NodeId *connectionIdentifier) {
32581 /* Find the matching UA_PubSubTransportLayers */
32582 UA_PubSubTransportLayer *tl = NULL;
32583 for(size_t i = 0; i < server->config.pubSubConfig.transportLayersSize; i++) {
32584 if(connectionConfig &&
32585 UA_String_equal(&server->config.pubSubConfig.transportLayers[i].transportProfileUri,
32586 &connectionConfig->transportProfileUri)) {
32587 tl = &server->config.pubSubConfig.transportLayers[i];
32588 }
32589 }
32590 if(!tl) {
32591 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32592 "PubSub Connection creation failed. Requested transport layer not found.");
32593 return UA_STATUSCODE_BADNOTFOUND;
32594 }
32595
32596 /* Create a copy of the connection config */
32597 UA_PubSubConnectionConfig *tmpConnectionConfig = (UA_PubSubConnectionConfig *)
32598 UA_calloc(1, sizeof(UA_PubSubConnectionConfig));
32599 if(!tmpConnectionConfig){
32600 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32601 "PubSub Connection creation failed. Out of Memory.");
32602 return UA_STATUSCODE_BADOUTOFMEMORY;
32603 }
32604
32605 UA_StatusCode retval = UA_PubSubConnectionConfig_copy(connectionConfig, tmpConnectionConfig);
32606 if(retval != UA_STATUSCODE_GOOD){
32607 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32608 "PubSub Connection creation failed. Could not copy the config.");
32609 return retval;
32610 }
32611
32612 /* Create new connection and add to UA_PubSubManager */
32613 UA_PubSubConnection *newConnectionsField = (UA_PubSubConnection *)
32614 UA_calloc(1, sizeof(UA_PubSubConnection));
32615 if(!newConnectionsField) {
32616 UA_PubSubConnectionConfig_clear(tmpConnectionConfig);
32617 UA_free(tmpConnectionConfig);
32618 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32619 "PubSub Connection creation failed. Out of Memory.");
32620 return UA_STATUSCODE_BADOUTOFMEMORY;
32621 }
32622 newConnectionsField->componentType = UA_PUBSUB_COMPONENT_CONNECTION;
32623 if (server->pubSubManager.connectionsSize != 0)
32624 TAILQ_INSERT_TAIL(&server->pubSubManager.connections, newConnectionsField, listEntry);
32625 else {
32626 TAILQ_INIT(&server->pubSubManager.connections);
32627 TAILQ_INSERT_HEAD(&server->pubSubManager.connections, newConnectionsField, listEntry);
32628 }
32629
32630 server->pubSubManager.connectionsSize++;
32631
32632 LIST_INIT(&newConnectionsField->writerGroups);
32633 newConnectionsField->config = tmpConnectionConfig;
32634
32635 /* Open the channel */
32636 newConnectionsField->channel = tl->createPubSubChannel(newConnectionsField->config);
32637 if(!newConnectionsField->channel) {
32638 UA_PubSubConnection_clear(server, newConnectionsField);
32639 TAILQ_REMOVE(&server->pubSubManager.connections, newConnectionsField, listEntry);
32640 server->pubSubManager.connectionsSize--;
32641 UA_free(newConnectionsField);
32642 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32643 "PubSub Connection creation failed. Transport layer creation problem.");
32644 return UA_STATUSCODE_BADINTERNALERROR;
32645 }
32646
32647#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32648 /* Internally createa a unique id */
32649 addPubSubConnectionRepresentation(server, newConnectionsField);
32650#else
32651 /* Create a unique NodeId that does not correspond to a Node */
32652 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
32653 &newConnectionsField->identifier);
32654#endif
32655
32656 if(connectionIdentifier)
32657 UA_NodeId_copy(&newConnectionsField->identifier, connectionIdentifier);
32658
32659 return UA_STATUSCODE_GOOD;
32660}
32661
32662UA_StatusCode
32663UA_Server_removePubSubConnection(UA_Server *server, const UA_NodeId connection) {
32664 //search the identified Connection and store the Connection index
32665 UA_PubSubConnection *currentConnection = UA_PubSubConnection_findConnectionbyId(server, connection);
32666 if(!currentConnection)
32667 return UA_STATUSCODE_BADNOTFOUND;
32668
32669 UA_WriterGroup *wg, *wg_tmp;
32670 LIST_FOREACH_SAFE(wg, &currentConnection->writerGroups, listEntry, wg_tmp) {
32671 UA_Server_unfreezeWriterGroupConfiguration(server, wg->identifier);
32672 UA_Server_removeWriterGroup(server, wg->identifier);
32673 }
32674
32675 UA_ReaderGroup *rg, *rg_tmp;
32676 LIST_FOREACH_SAFE(rg, &currentConnection->readerGroups, listEntry, rg_tmp) {
32677 UA_Server_unfreezeReaderGroupConfiguration(server, rg->identifier);
32678 UA_Server_removeReaderGroup(server, rg->identifier);
32679 }
32680
32681#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32682 removePubSubConnectionRepresentation(server, currentConnection);
32683#endif
32684 server->pubSubManager.connectionsSize--;
32685
32686 UA_PubSubConnection_clear(server, currentConnection);
32687 TAILQ_REMOVE(&server->pubSubManager.connections, currentConnection, listEntry);
32688 UA_free(currentConnection);
32689 return UA_STATUSCODE_GOOD;
32690}
32691
32692UA_StatusCode
32693UA_PubSubConnection_regist(UA_Server *server, UA_NodeId *connectionIdentifier) {
32694 UA_PubSubConnection *connection =
32695 UA_PubSubConnection_findConnectionbyId(server, *connectionIdentifier);
32696 if(!connection)
32697 return UA_STATUSCODE_BADNOTFOUND;
32698
32699 if(connection->isRegistered) {
32700 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "Connection already registered");
32701 return UA_STATUSCODE_GOOD;
32702 }
32703
32704 UA_StatusCode retval = connection->channel->regist(connection->channel, NULL, NULL);
32705 if(retval != UA_STATUSCODE_GOOD)
32706 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32707 "register channel failed: 0x%" PRIx32 "!", retval);
32708
32709 connection->isRegistered = UA_TRUE;
32710 return retval;
32711}
32712
32713UA_AddPublishedDataSetResult
32714UA_Server_addPublishedDataSet(UA_Server *server,
32715 const UA_PublishedDataSetConfig *publishedDataSetConfig,
32716 UA_NodeId *pdsIdentifier) {
32717 UA_AddPublishedDataSetResult result = {UA_STATUSCODE_BADINVALIDARGUMENT, 0, NULL, {0, 0}};
32718 if(!publishedDataSetConfig){
32719 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32720 "PublishedDataSet creation failed. No config passed in.");
32721 return result;
32722 }
32723
32724 if(publishedDataSetConfig->publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS){
32725 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32726 "PublishedDataSet creation failed. Unsupported PublishedDataSet type.");
32727 return result;
32728 }
32729
32730 /* Create new PDS and add to UA_PubSubManager */
32731 UA_PublishedDataSet *newPDS = (UA_PublishedDataSet *)
32732 UA_calloc(1, sizeof(UA_PublishedDataSet));
32733 if(!newPDS) {
32734 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32735 "PublishedDataSet creation failed. Out of Memory.");
32736 result.addResult = UA_STATUSCODE_BADOUTOFMEMORY;
32737 return result;
32738 }
32739 TAILQ_INIT(&newPDS->fields);
32740
32741 UA_PublishedDataSetConfig *newConfig = &newPDS->config;
32742
32743 /* Deep copy the given connection config */
32744 UA_StatusCode res = UA_PublishedDataSetConfig_copy(publishedDataSetConfig, newConfig);
32745 if(res != UA_STATUSCODE_GOOD){
32746 UA_free(newPDS);
32747 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32748 "PublishedDataSet creation failed. Configuration copy failed.");
32749 result.addResult = UA_STATUSCODE_BADINTERNALERROR;
32750 return result;
32751 }
32752
32753 /* TODO: Parse template config and add fields (later PubSub batch) */
32754 if(newConfig->publishedDataSetType == UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE) {
32755 }
32756
32757 /* Fill the DataSetMetaData */
32758 result.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
32759 result.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
32760 switch(newConfig->publishedDataSetType) {
32761 case UA_PUBSUB_DATASET_PUBLISHEDEVENTS_TEMPLATE:
32762 res = UA_STATUSCODE_BADNOTSUPPORTED;
32763 break;
32764 case UA_PUBSUB_DATASET_PUBLISHEDEVENTS:
32765 res = UA_STATUSCODE_BADNOTSUPPORTED;
32766 break;
32767 case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
32768 newPDS->dataSetMetaData.configurationVersion.majorVersion =
32769 UA_PubSubConfigurationVersionTimeDifference();
32770 newPDS->dataSetMetaData.configurationVersion.minorVersion =
32771 UA_PubSubConfigurationVersionTimeDifference();
32772 newPDS->dataSetMetaData.description = UA_LOCALIZEDTEXT_ALLOC("", "");
32773 newPDS->dataSetMetaData.dataSetClassId = UA_GUID_NULL;
32774 res = UA_String_copy(&newConfig->name, &newPDS->dataSetMetaData.name);
32775 break;
32776 case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
32777 res = UA_DataSetMetaDataType_copy(&newConfig->config.itemsTemplate.metaData,
32778 &newPDS->dataSetMetaData);
32779 break;
32780 default:
32781 res = UA_STATUSCODE_BADINTERNALERROR;
32782 }
32783
32784 /* Abort? */
32785 result.addResult = res;
32786 if(result.addResult != UA_STATUSCODE_GOOD) {
32787 UA_PublishedDataSetConfig_clear(newConfig);
32788 UA_free(newPDS);
32789 return result;
32790 }
32791
32792 /* Insert into the queue of the manager */
32793 if(server->pubSubManager.publishedDataSetsSize != 0) {
32794 TAILQ_INSERT_TAIL(&server->pubSubManager.publishedDataSets,
32795 newPDS, listEntry);
32796 } else {
32797 TAILQ_INIT(&server->pubSubManager.publishedDataSets);
32798 TAILQ_INSERT_HEAD(&server->pubSubManager.publishedDataSets,
32799 newPDS, listEntry);
32800 }
32801 server->pubSubManager.publishedDataSetsSize++;
32802
32803#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32804 /* Create representation and unique id */
32805 addPublishedDataItemsRepresentation(server, newPDS);
32806#else
32807 /* Generate unique nodeId */
32808 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, &newPDS->identifier);
32809#endif
32810 if(pdsIdentifier)
32811 UA_NodeId_copy(&newPDS->identifier, pdsIdentifier);
32812
32813 return result;
32814}
32815
32816UA_StatusCode
32817UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds) {
32818 //search the identified PublishedDataSet and store the PDS index
32819 UA_PublishedDataSet *publishedDataSet = UA_PublishedDataSet_findPDSbyId(server, pds);
32820 if(!publishedDataSet){
32821 return UA_STATUSCODE_BADNOTFOUND;
32822 }
32823 if(publishedDataSet->configurationFrozen){
32824 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32825 "Remove PublishedDataSet failed. PublishedDataSet is frozen.");
32826 return UA_STATUSCODE_BADCONFIGURATIONERROR;
32827 }
32828
32829 //search for referenced writers -> delete this writers. (Standard: writer must be connected with PDS)
32830 UA_PubSubConnection *tmpConnectoin;
32831 TAILQ_FOREACH(tmpConnectoin, &server->pubSubManager.connections, listEntry){
32832 UA_WriterGroup *writerGroup;
32833 LIST_FOREACH(writerGroup, &tmpConnectoin->writerGroups, listEntry){
32834 UA_DataSetWriter *currentWriter, *tmpWriterGroup;
32835 LIST_FOREACH_SAFE(currentWriter, &writerGroup->writers, listEntry, tmpWriterGroup){
32836 if(UA_NodeId_equal(&currentWriter->connectedDataSet, &publishedDataSet->identifier)){
32837 UA_Server_removeDataSetWriter(server, currentWriter->identifier);
32838 }
32839 }
32840 }
32841 }
32842#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32843 removePublishedDataSetRepresentation(server, publishedDataSet);
32844#endif
32845 UA_PublishedDataSet_clear(server, publishedDataSet);
32846 server->pubSubManager.publishedDataSetsSize--;
32847
32848 TAILQ_REMOVE(&server->pubSubManager.publishedDataSets, publishedDataSet, listEntry);
32849 UA_free(publishedDataSet);
32850 return UA_STATUSCODE_GOOD;
32851}
32852
32853/* Calculate the time difference between current time and UTC (00:00) on January
32854 * 1, 2000. */
32855UA_UInt32
32856UA_PubSubConfigurationVersionTimeDifference(void) {
32857 UA_UInt32 timeDiffSince2000 = (UA_UInt32) (UA_DateTime_now() - UA_DATETIMESTAMP_2000);
32858 return timeDiffSince2000;
32859}
32860
32861/* Generate a new unique NodeId. This NodeId will be used for the information
32862 * model representation of PubSub entities. */
32863#ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32864void
32865UA_PubSubManager_generateUniqueNodeId(UA_PubSubManager *psm, UA_NodeId *nodeId) {
32866 *nodeId = UA_NODEID_NUMERIC(1, ++psm->uniqueIdCount);
32867}
32868#endif
32869
32870UA_Guid
32871UA_PubSubManager_generateUniqueGuid(UA_Server *server) {
32872 while(true) {
32873 UA_NodeId testId = UA_NODEID_GUID(1, UA_Guid_random());
32874 const UA_Node *testNode = UA_NODESTORE_GET(server, &testId);
32875 if(!testNode)
32876 return testId.identifier.guid;
32877 UA_NODESTORE_RELEASE(server, testNode);
32878 }
32879}
32880
32881/* Delete the current PubSub configuration including all nested members. This
32882 * action also delete the configured PubSub transport Layers. */
32883void
32884UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager) {
32885 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "PubSub cleanup was called.");
32886
32887 /* Stop and unfreeze all WriterGroups */
32888 UA_PubSubConnection *tmpConnection;
32889 TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry){
32890 for(size_t i = 0; i < pubSubManager->connectionsSize; i++) {
32891 UA_WriterGroup *writerGroup;
32892 LIST_FOREACH(writerGroup, &tmpConnection->writerGroups, listEntry) {
32893 UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, writerGroup);
32894 UA_Server_unfreezeWriterGroupConfiguration(server, writerGroup->identifier);
32895 }
32896 }
32897 }
32898
32899 //free the currently configured transport layers
32900 if(server->config.pubSubConfig.transportLayersSize > 0) {
32901 UA_free(server->config.pubSubConfig.transportLayers);
32902 server->config.pubSubConfig.transportLayersSize = 0;
32903 }
32904
32905 //remove Connections and WriterGroups
32906 UA_PubSubConnection *tmpConnection1, *tmpConnection2;
32907 TAILQ_FOREACH_SAFE(tmpConnection1, &server->pubSubManager.connections, listEntry, tmpConnection2){
32908 UA_Server_removePubSubConnection(server, tmpConnection1->identifier);
32909 }
32910 UA_PublishedDataSet *tmpPDS1, *tmpPDS2;
32911 TAILQ_FOREACH_SAFE(tmpPDS1, &server->pubSubManager.publishedDataSets, listEntry, tmpPDS2){
32912 UA_Server_removePublishedDataSet(server, tmpPDS1->identifier);
32913 }
32914}
32915
32916/***********************************/
32917/* PubSub Jobs abstraction */
32918/***********************************/
32919
32920/* Default Timer based PubSub Callbacks */
32921
32922UA_StatusCode
32923UA_PubSubManager_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
32924 void *data, UA_Double interval_ms, UA_DateTime *baseTime,
32925 UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId) {
32926 return UA_Timer_addRepeatedCallback(&server->timer, (UA_ApplicationCallback)callback,
32927 server, data, interval_ms, baseTime, timerPolicy, callbackId);
32928}
32929
32930UA_StatusCode
32931UA_PubSubManager_changeRepeatedCallback(UA_Server *server, UA_UInt64 callbackId,
32932 UA_Double interval_ms, UA_DateTime *baseTime,
32933 UA_TimerPolicy timerPolicy) {
32934 return UA_Timer_changeRepeatedCallback(&server->timer, callbackId, interval_ms, baseTime, timerPolicy);
32935}
32936
32937void
32938UA_PubSubManager_removeRepeatedPubSubCallback(UA_Server *server, UA_UInt64 callbackId) {
32939 UA_Timer_removeCallback(&server->timer, callbackId);
32940}
32941
32942
32943#ifdef UA_ENABLE_PUBSUB_MONITORING
32944
32945static UA_StatusCode
32946UA_PubSubComponent_createMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
32947 UA_PubSubMonitoringType eMonitoringType, void *data, UA_ServerCallback callback) {
32948
32949 if ((!server) || (!data)) {
32950 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_createMonitoring(): "
32951 "null pointer param");
32952 return UA_STATUSCODE_BADINVALIDARGUMENT;
32953 }
32954 UA_StatusCode ret = UA_STATUSCODE_GOOD;
32955 switch (eComponentType) {
32956 case UA_PUBSUB_COMPONENT_DATASETREADER: {
32957 UA_DataSetReader *reader = (UA_DataSetReader*) data;
32958 switch (eMonitoringType) {
32959 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT:
32960 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' "
32961 "- MessageReceiveTimeout", (UA_Int32) reader->config.name.length, reader->config.name.data);
32962 reader->msgRcvTimeoutTimerCallback = callback;
32963 break;
32964 default:
32965 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' "
32966 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
32967 eMonitoringType);
32968 ret = UA_STATUSCODE_BADNOTSUPPORTED;
32969 break;
32970 }
32971 break;
32972 }
32973 default:
32974 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32975 "Error UA_PubSubComponent_createMonitoring(): PubSub component type '%i' is not supported", eComponentType);
32976 ret = UA_STATUSCODE_BADNOTSUPPORTED;
32977 break;
32978 }
32979 return ret;
32980}
32981
32982static UA_StatusCode
32983UA_PubSubComponent_startMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
32984 UA_PubSubMonitoringType eMonitoringType, void *data) {
32985
32986 if ((!server) || (!data)) {
32987 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_startMonitoring(): "
32988 "null pointer param");
32989 return UA_STATUSCODE_BADINVALIDARGUMENT;
32990 }
32991
32992 UA_StatusCode ret = UA_STATUSCODE_GOOD;
32993 switch (eComponentType) {
32994 case UA_PUBSUB_COMPONENT_DATASETREADER: {
32995 UA_DataSetReader *reader = (UA_DataSetReader*) data;
32996 switch (eMonitoringType) {
32997 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: {
32998 /* use a timed callback, because one notification is enough,
32999 we assume that MessageReceiveTimeout configuration is in [ms], we do not handle or check fractions */
33000 UA_UInt64 interval = (UA_UInt64)(reader->config.messageReceiveTimeout * UA_DATETIME_MSEC);
33001 ret = UA_Timer_addTimedCallback(&server->timer, (UA_ApplicationCallback) reader->msgRcvTimeoutTimerCallback,
33002 server, reader, UA_DateTime_nowMonotonic() + (UA_DateTime) interval, &(reader->msgRcvTimeoutTimerId));
33003 if (ret == UA_STATUSCODE_GOOD) {
33004 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
33005 "UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s'- MessageReceiveTimeout: MessageReceiveTimeout = '%f' "
33006 "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33007 reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
33008 } else {
33009 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33010 "Error UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: start timer failed",
33011 (UA_Int32) reader->config.name.length, reader->config.name.data);
33012 }
33013 break;
33014 }
33015 default:
33016 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s' "
33017 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33018 eMonitoringType);
33019 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33020 break;
33021 }
33022 break;
33023 }
33024 default:
33025 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33026 "Error UA_PubSubComponent_startMonitoring(): PubSub component type '%i' is not supported", eComponentType);
33027 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33028 break;
33029 }
33030 return ret;
33031}
33032
33033static UA_StatusCode
33034UA_PubSubComponent_stopMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
33035 UA_PubSubMonitoringType eMonitoringType, void *data) {
33036
33037 if ((!server) || (!data)) {
33038 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_stopMonitoring(): "
33039 "null pointer param");
33040 return UA_STATUSCODE_BADINVALIDARGUMENT;
33041 }
33042
33043 UA_StatusCode ret = UA_STATUSCODE_GOOD;
33044 switch (eComponentType) {
33045 case UA_PUBSUB_COMPONENT_DATASETREADER: {
33046 UA_DataSetReader *reader = (UA_DataSetReader*) data;
33047 switch (eMonitoringType) {
33048 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: {
33049 UA_Timer_removeCallback(&server->timer, reader->msgRcvTimeoutTimerId);
33050 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
33051 "UA_PubSubComponent_stopMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: MessageReceiveTimeout = '%f' "
33052 "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33053 reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
33054 break;
33055 }
33056 default:
33057 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_stopMonitoring(): DataSetReader '%.*s' "
33058 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33059 eMonitoringType);
33060 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33061 break;
33062 }
33063 break;
33064 }
33065 default:
33066 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33067 "Error UA_PubSubComponent_stopMonitoring(): PubSub component type '%i' is not supported", eComponentType);
33068 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33069 break;
33070 }
33071 return ret;
33072}
33073
33074static UA_StatusCode
33075UA_PubSubComponent_updateMonitoringInterval(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
33076 UA_PubSubMonitoringType eMonitoringType, void *data)
33077{
33078 if ((!server) || (!data)) {
33079 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_updateMonitoringInterval(): "
33080 "null pointer param");
33081 return UA_STATUSCODE_BADINVALIDARGUMENT;
33082 }
33083 UA_StatusCode ret = UA_STATUSCODE_GOOD;
33084 switch (eComponentType) {
33085 case UA_PUBSUB_COMPONENT_DATASETREADER: {
33086 UA_DataSetReader *reader = (UA_DataSetReader*) data;
33087 switch (eMonitoringType) {
33088 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: {
33089 ret = UA_Timer_changeRepeatedCallback(&server->timer, reader->msgRcvTimeoutTimerId,
33090 reader->config.messageReceiveTimeout, NULL,
33091 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
33092 if (ret == UA_STATUSCODE_GOOD) {
33093 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
33094 "UA_PubSubComponent_updateMonitoringInterval(): DataSetReader '%.*s' - MessageReceiveTimeout: new MessageReceiveTimeout = '%f' "
33095 "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33096 reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
33097 } else {
33098 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33099 "Error UA_PubSubComponent_updateMonitoringInterval(): DataSetReader '%.*s': update timer interval failed",
33100 (UA_Int32) reader->config.name.length, reader->config.name.data);
33101 }
33102 break;
33103 }
33104 default:
33105 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' "
33106 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33107 eMonitoringType);
33108 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33109 break;
33110 }
33111 break;
33112 }
33113 default:
33114 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33115 "Error UA_PubSubComponent_updateMonitoringInterval(): PubSub component type '%i' is not supported", eComponentType);
33116 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33117 break;
33118 }
33119 return ret;
33120}
33121
33122static UA_StatusCode
33123UA_PubSubComponent_deleteMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
33124 UA_PubSubMonitoringType eMonitoringType, void *data) {
33125
33126 if ((!server) || (!data)) {
33127 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_deleteMonitoring(): "
33128 "null pointer param");
33129 return UA_STATUSCODE_BADINVALIDARGUMENT;
33130 }
33131 UA_StatusCode ret = UA_STATUSCODE_GOOD;
33132 switch (eComponentType) {
33133 case UA_PUBSUB_COMPONENT_DATASETREADER: {
33134 UA_DataSetReader *reader = (UA_DataSetReader*) data;
33135 switch (eMonitoringType) {
33136 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT:
33137 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
33138 "UA_PubSubComponent_deleteMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: Timer Id = '%u'",
33139 (UA_Int32) reader->config.name.length, reader->config.name.data, (UA_UInt32) reader->msgRcvTimeoutTimerId);
33140 break;
33141 default:
33142 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_deleteMonitoring(): DataSetReader '%.*s' "
33143 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33144 eMonitoringType);
33145 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33146 break;
33147 }
33148 break;
33149 }
33150 default:
33151 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33152 "Error UA_PubSubComponent_deleteMonitoring(): PubSub component type '%i' is not supported", eComponentType);
33153 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33154 break;
33155 }
33156 return ret;
33157}
33158
33159UA_StatusCode
33160UA_PubSubManager_setDefaultMonitoringCallbacks(UA_PubSubMonitoringInterface *monitoringInterface) {
33161 if (monitoringInterface == NULL) {
33162 return UA_STATUSCODE_BADINVALIDARGUMENT;
33163 }
33164 monitoringInterface->createMonitoring = UA_PubSubComponent_createMonitoring;
33165 monitoringInterface->startMonitoring = UA_PubSubComponent_startMonitoring;
33166 monitoringInterface->stopMonitoring = UA_PubSubComponent_stopMonitoring;
33167 monitoringInterface->updateMonitoringInterval = UA_PubSubComponent_updateMonitoringInterval;
33168 monitoringInterface->deleteMonitoring = UA_PubSubComponent_deleteMonitoring;
33169 return UA_STATUSCODE_GOOD;
33170}
33171
33172#endif /* UA_ENABLE_PUBSUB_MONITORING */
33173
33174#endif /* UA_ENABLE_PUBSUB */
33175
33176/**** amalgamated original file "/src/pubsub/ua_pubsub_ns0.c" ****/
33177
33178/* This Source Code Form is subject to the terms of the Mozilla Public
33179 * License, v. 2.0. If a copy of the MPL was not distributed with this
33180 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
33181 *
33182 * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
33183 * Copyright (c) 2019-2021 Kalycito Infotech Private Limited
33184 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
33185 * Copyright (c) 2020 Thomas Fischer, Siemens AG
33186 */
33187
33188
33189#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
33190#endif
33191
33192#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL /* conditional compilation */
33193
33194typedef struct {
33195 UA_NodeId parentNodeId;
33196 UA_UInt32 parentClassifier;
33197 UA_UInt32 elementClassiefier;
33198} UA_NodePropertyContext;
33199
33200static UA_StatusCode
33201writePubSubNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
33202 size_t length, const UA_DataType *type) {
33203 UA_Variant var;
33204 UA_Variant_init(&var);
33205 UA_Variant_setArray(&var, v, length, type);
33206 return UA_Server_writeValue(server, UA_NODEID_NUMERIC(0, id), var);
33207}
33208
33209static UA_NodeId
33210findSingleChildNode(UA_Server *server, UA_QualifiedName targetName,
33211 UA_NodeId referenceTypeId, UA_NodeId startingNode){
33212 UA_NodeId resultNodeId;
33213 UA_RelativePathElement rpe;
33214 UA_RelativePathElement_init(&rpe);
33215 rpe.referenceTypeId = referenceTypeId;
33216 rpe.isInverse = false;
33217 rpe.includeSubtypes = false;
33218 rpe.targetName = targetName;
33219 UA_BrowsePath bp;
33220 UA_BrowsePath_init(&bp);
33221 bp.startingNode = startingNode;
33222 bp.relativePath.elementsSize = 1;
33223 bp.relativePath.elements = &rpe;
33224 UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp);
33225 if(bpr.statusCode != UA_STATUSCODE_GOOD ||
33226 bpr.targetsSize < 1)
33227 return UA_NODEID_NULL;
33228 UA_StatusCode res = UA_NodeId_copy(&bpr.targets[0].targetId.nodeId, &resultNodeId);
33229 if(res != UA_STATUSCODE_GOOD){
33230 UA_BrowsePathResult_clear(&bpr);
33231 return UA_NODEID_NULL;
33232 }
33233 UA_BrowsePathResult_clear(&bpr);
33234 return resultNodeId;
33235}
33236
33237static void
33238onRead(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
33239 const UA_NodeId *nodeid, void *context,
33240 const UA_NumericRange *range, const UA_DataValue *data) {
33241 UA_Variant value;
33242 UA_Variant_init(&value);
33243 const UA_NodePropertyContext *nodeContext = (const UA_NodePropertyContext*)context;
33244 const UA_NodeId *myNodeId = &nodeContext->parentNodeId;
33245
33246 switch(nodeContext->parentClassifier){
33247 case UA_NS0ID_PUBSUBCONNECTIONTYPE: {
33248 UA_PubSubConnection *pubSubConnection =
33249 UA_PubSubConnection_findConnectionbyId(server, *myNodeId);
33250 switch(nodeContext->elementClassiefier) {
33251 case UA_NS0ID_PUBSUBCONNECTIONTYPE_PUBLISHERID:
33252 if(pubSubConnection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING) {
33253 UA_Variant_setScalarCopy(&value, &pubSubConnection->config->publisherId.numeric,
33254 &UA_TYPES[UA_TYPES_STRING]);
33255 } else {
33256 UA_Variant_setScalarCopy(&value, &pubSubConnection->config->publisherId.numeric,
33257 &UA_TYPES[UA_TYPES_UINT32]);
33258 }
33259 break;
33260 default:
33261 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33262 "Read error! Unknown property.");
33263 }
33264 break;
33265 }
33266 case UA_NS0ID_DATASETREADERTYPE: {
33267 UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, *myNodeId);
33268 if(!dataSetReader)
33269 return;
33270
33271 switch(nodeContext->elementClassiefier) {
33272 case UA_NS0ID_DATASETREADERTYPE_PUBLISHERID:
33273 UA_Variant_setScalarCopy(&value, dataSetReader->config.publisherId.data,
33274 dataSetReader->config.publisherId.type);
33275 break;
33276 default:
33277 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33278 "Read error! Unknown property.");
33279 }
33280 break;
33281 }
33282 case UA_NS0ID_WRITERGROUPTYPE: {
33283 UA_WriterGroup *writerGroup = UA_WriterGroup_findWGbyId(server, *myNodeId);
33284 if(!writerGroup)
33285 return;
33286 switch(nodeContext->elementClassiefier){
33287 case UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL:
33288 UA_Variant_setScalarCopy(&value, &writerGroup->config.publishingInterval,
33289 &UA_TYPES[UA_TYPES_DURATION]);
33290 break;
33291 default:
33292 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33293 "Read error! Unknown property.");
33294 }
33295 break;
33296 }
33297 case UA_NS0ID_DATASETWRITERTYPE: {
33298 UA_DataSetWriter *dataSetWriter = UA_DataSetWriter_findDSWbyId(server, *myNodeId);
33299 if(!dataSetWriter)
33300 return;
33301
33302 switch(nodeContext->elementClassiefier) {
33303 case UA_NS0ID_DATASETWRITERTYPE_DATASETWRITERID:
33304 UA_Variant_setScalarCopy(&value, &dataSetWriter->config.dataSetWriterId,
33305 &UA_TYPES[UA_TYPES_UINT16]);
33306 break;
33307 default:
33308 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33309 "Read error! Unknown property.");
33310 }
33311 break;
33312 }
33313 case UA_NS0ID_PUBLISHEDDATAITEMSTYPE: {
33314 UA_PublishedDataSet *publishedDataSet = UA_PublishedDataSet_findPDSbyId(server, *myNodeId);
33315 if(!publishedDataSet)
33316 return;
33317 switch(nodeContext->elementClassiefier) {
33318 case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_PUBLISHEDDATA: {
33319 UA_PublishedVariableDataType *pvd = (UA_PublishedVariableDataType *)
33320 UA_calloc(publishedDataSet->fieldSize, sizeof(UA_PublishedVariableDataType));
33321 size_t counter = 0;
33322 UA_DataSetField *field;
33323 TAILQ_FOREACH(field, &publishedDataSet->fields, listEntry) {
33324 pvd[counter].attributeId = UA_ATTRIBUTEID_VALUE;
33325 UA_NodeId_copy(&field->config.field.variable.publishParameters.publishedVariable, &pvd[counter].publishedVariable);
33326 counter++;
33327 }
33328 UA_Variant_setArray(&value, pvd, publishedDataSet->fieldSize,
33329 &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]);
33330 break;
33331 }
33332 case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_DATASETMETADATA: {
33333 UA_Variant_setScalarCopy(&value, &publishedDataSet->dataSetMetaData, &UA_TYPES[UA_TYPES_DATASETMETADATATYPE]);
33334 break;
33335 }
33336 case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_CONFIGURATIONVERSION: {
33337 UA_Variant_setScalarCopy(&value, &publishedDataSet->dataSetMetaData.configurationVersion,
33338 &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE]);
33339 break;
33340 }
33341 default:
33342 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33343 "Read error! Unknown property.");
33344 }
33345 break;
33346 }
33347 default:
33348 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33349 "Read error! Unknown parent element.");
33350 }
33351 UA_Server_writeValue(server, *nodeid, value);
33352 UA_Variant_clear(&value);
33353}
33354
33355static void
33356onWrite(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
33357 const UA_NodeId *nodeId, void *nodeContext,
33358 const UA_NumericRange *range, const UA_DataValue *data){
33359 UA_Variant value;
33360 UA_NodeId myNodeId;
33361 UA_WriterGroup *writerGroup = NULL;
33362 switch(((UA_NodePropertyContext *) nodeContext)->parentClassifier){
33363 case UA_NS0ID_PUBSUBCONNECTIONTYPE:
33364 //no runtime writable attributes
33365 break;
33366 case UA_NS0ID_WRITERGROUPTYPE:
33367 myNodeId = ((UA_NodePropertyContext *) nodeContext)->parentNodeId;
33368 writerGroup = UA_WriterGroup_findWGbyId(server, myNodeId);
33369 UA_WriterGroupConfig writerGroupConfig;
33370 memset(&writerGroupConfig, 0, sizeof(writerGroupConfig));
33371 if(!writerGroup)
33372 return;
33373 switch(((UA_NodePropertyContext *) nodeContext)->elementClassiefier){
33374 case UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL:
33375 UA_Server_getWriterGroupConfig(server, writerGroup->identifier, &writerGroupConfig);
33376 writerGroupConfig.publishingInterval = *((UA_Duration *) data->value.data);
33377 UA_Server_updateWriterGroupConfig(server, writerGroup->identifier, &writerGroupConfig);
33378 UA_Variant_setScalar(&value, data->value.data, &UA_TYPES[UA_TYPES_DURATION]);
33379 UA_WriterGroupConfig_clear(&writerGroupConfig);
33380 break;
33381 default:
33382 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33383 "Write error! Unknown property element.");
33384 }
33385 break;
33386 default:
33387 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33388 "Read error! Unknown parent element.");
33389 }
33390}
33391
33392static UA_StatusCode
33393addVariableValueSource(UA_Server *server, UA_ValueCallback valueCallback,
33394 UA_NodeId node, UA_NodePropertyContext *context){
33395 UA_Server_setNodeContext(server, node, context);
33396 return UA_Server_setVariableNode_valueCallback(server, node, valueCallback);
33397}
33398
33399#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33400static UA_StatusCode
33401addPubSubConnectionConfig(UA_Server *server, UA_PubSubConnectionDataType *pubsubConnectionDataType,
33402 UA_NodeId *connectionId){
33403 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33404 UA_NetworkAddressUrlDataType networkAddressUrlDataType;
33405 memset(&networkAddressUrlDataType, 0, sizeof(networkAddressUrlDataType));
33406 UA_ExtensionObject eo = pubsubConnectionDataType->address;
33407 if(eo.encoding == UA_EXTENSIONOBJECT_DECODED){
33408 if(eo.content.decoded.type == &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]){
33409 if(UA_NetworkAddressUrlDataType_copy((UA_NetworkAddressUrlDataType *) eo.content.decoded.data,
33410 &networkAddressUrlDataType) != UA_STATUSCODE_GOOD){
33411 return UA_STATUSCODE_BADOUTOFMEMORY;
33412 }
33413 }
33414 }
33415
33416 UA_PubSubConnectionConfig connectionConfig;
33417 memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig));
33418 connectionConfig.transportProfileUri = pubsubConnectionDataType->transportProfileUri;
33419 connectionConfig.name = pubsubConnectionDataType->name;
33420 //TODO set real connection state
33421 connectionConfig.enabled = pubsubConnectionDataType->enabled;
33422 //connectionConfig.enabled = pubSubConnectionDataType.enabled;
33423 UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrlDataType,
33424 &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
33425 if(pubsubConnectionDataType->publisherId.type == &UA_TYPES[UA_TYPES_UINT32]){
33426 connectionConfig.publisherId.numeric = * ((UA_UInt32 *) pubsubConnectionDataType->publisherId.data);
33427 } else if(pubsubConnectionDataType->publisherId.type == &UA_TYPES[UA_TYPES_STRING]){
33428 connectionConfig.publisherIdType = UA_PUBSUB_PUBLISHERID_STRING;
33429 UA_String_copy((UA_String *) pubsubConnectionDataType->publisherId.data, &connectionConfig.publisherId.string);
33430 } else {
33431 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER, "Unsupported PublisherId Type used.");
33432 //TODO what's the best default behaviour here?
33433 connectionConfig.publisherId.numeric = 0;
33434 }
33435
33436 retVal |= UA_Server_addPubSubConnection(server, &connectionConfig, connectionId);
33437 UA_NetworkAddressUrlDataType_clear(&networkAddressUrlDataType);
33438 return retVal;
33439}
33440
33441/**
33442 * **WriterGroup handling**
33443 *
33444 * The WriterGroup (WG) is part of the connection and contains the primary
33445 * configuration parameters for the message creation. */
33446static UA_StatusCode
33447addWriterGroupConfig(UA_Server *server, UA_NodeId connectionId,
33448 UA_WriterGroupDataType *writerGroupDataType, UA_NodeId *writerGroupId){
33449 /* Now we create a new WriterGroupConfig and add the group to the existing
33450 * PubSubConnection. */
33451 UA_WriterGroupConfig writerGroupConfig;
33452 memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig));
33453 writerGroupConfig.name = writerGroupDataType->name;
33454 writerGroupConfig.publishingInterval = writerGroupDataType->publishingInterval;
33455 writerGroupConfig.enabled = writerGroupDataType->enabled;
33456 writerGroupConfig.writerGroupId = writerGroupDataType->writerGroupId;
33457 //TODO remove hard coded UADP
33458 writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
33459 writerGroupConfig.priority = writerGroupDataType->priority;
33460
33461 UA_UadpWriterGroupMessageDataType writerGroupMessage;
33462 UA_ExtensionObject *eoWG = &writerGroupDataType->messageSettings;
33463 if(eoWG->encoding == UA_EXTENSIONOBJECT_DECODED){
33464 writerGroupConfig.messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
33465 if(eoWG->content.decoded.type == &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]){
33466 if(UA_UadpWriterGroupMessageDataType_copy((UA_UadpWriterGroupMessageDataType *) eoWG->content.decoded.data,
33467 &writerGroupMessage) != UA_STATUSCODE_GOOD){
33468 return UA_STATUSCODE_BADOUTOFMEMORY;
33469 }
33470 writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
33471 writerGroupConfig.messageSettings.content.decoded.data = &writerGroupMessage;
33472 }
33473 }
33474
33475 return UA_Server_addWriterGroup(server, connectionId, &writerGroupConfig, writerGroupId);
33476}
33477
33478/**
33479 * **DataSetWriter handling**
33480 *
33481 * A DataSetWriter (DSW) is the glue between the WG and the PDS. The DSW is
33482 * linked to exactly one PDS and contains additional informations for the
33483 * message generation. */
33484static UA_StatusCode
33485addDataSetWriterConfig(UA_Server *server, const UA_NodeId *writerGroupId,
33486 UA_DataSetWriterDataType *dataSetWriterDataType,
33487 UA_NodeId *dataSetWriterId) {
33488 UA_NodeId publishedDataSetId = UA_NODEID_NULL;
33489 UA_PublishedDataSet *tmpPDS;
33490 TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry){
33491 if(UA_String_equal(&dataSetWriterDataType->dataSetName, &tmpPDS->config.name)) {
33492 publishedDataSetId = tmpPDS->identifier;
33493 break;
33494 }
33495 }
33496
33497 if(UA_NodeId_isNull(&publishedDataSetId))
33498 return UA_STATUSCODE_BADPARENTNODEIDINVALID;
33499
33500 /* We need now a DataSetWriter within the WriterGroup. This means we must
33501 * create a new DataSetWriterConfig and add call the addWriterGroup function. */
33502 UA_DataSetWriterConfig dataSetWriterConfig;
33503 memset(&dataSetWriterConfig, 0, sizeof(UA_DataSetWriterConfig));
33504 dataSetWriterConfig.name = dataSetWriterDataType->name;
33505 dataSetWriterConfig.dataSetWriterId = dataSetWriterDataType->dataSetWriterId;
33506 dataSetWriterConfig.keyFrameCount = dataSetWriterDataType->keyFrameCount;
33507 dataSetWriterConfig.dataSetFieldContentMask = dataSetWriterDataType->dataSetFieldContentMask;
33508 return UA_Server_addDataSetWriter(server, *writerGroupId, publishedDataSetId,
33509 &dataSetWriterConfig, dataSetWriterId);
33510}
33511
33512/**
33513 * **ReaderGroup**
33514 *
33515 * ReaderGroup is used to group a list of DataSetReaders. All ReaderGroups are
33516 * created within a PubSubConnection and automatically deleted if the connection
33517 * is removed. All network message related filters are only available in the DataSetReader. */
33518/* Add ReaderGroup to the created connection */
33519static UA_StatusCode
33520addReaderGroupConfig(UA_Server *server, UA_NodeId connectionId,
33521 UA_ReaderGroupDataType *readerGroupDataType,
33522 UA_NodeId *readerGroupId) {
33523 UA_ReaderGroupConfig readerGroupConfig;
33524 memset(&readerGroupConfig, 0, sizeof(UA_ReaderGroupConfig));
33525 readerGroupConfig.name = readerGroupDataType->name;
33526 return UA_Server_addReaderGroup(server, connectionId,
33527 &readerGroupConfig, readerGroupId);
33528}
33529
33530/**
33531 * **SubscribedDataSet**
33532 *
33533 * Set SubscribedDataSet type to TargetVariables data type.
33534 * Add subscribedvariables to the DataSetReader */
33535static UA_StatusCode
33536addSubscribedVariables(UA_Server *server, UA_NodeId dataSetReaderId,
33537 UA_DataSetReaderDataType *dataSetReaderDataType,
33538 UA_DataSetMetaDataType *pMetaData) {
33539 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33540 UA_ExtensionObject *eoTargetVar = &dataSetReaderDataType->subscribedDataSet;
33541 if(eoTargetVar->encoding != UA_EXTENSIONOBJECT_DECODED ||
33542 eoTargetVar->content.decoded.type != &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE])
33543 return UA_STATUSCODE_BADINTERNALERROR;
33544
33545 const UA_TargetVariablesDataType *targetVars =
33546 (UA_TargetVariablesDataType *) eoTargetVar->content.decoded.data;
33547
33548 UA_NodeId folderId;
33549 UA_String folderName = pMetaData->name;
33550 UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
33551 UA_QualifiedName folderBrowseName;
33552 if(folderName.length > 0) {
33553 oAttr.displayName.locale = UA_STRING("");
33554 oAttr.displayName.text = folderName;
33555 folderBrowseName.namespaceIndex = 1;
33556 folderBrowseName.name = folderName;
33557 } else {
33558 oAttr.displayName = UA_LOCALIZEDTEXT("", "Subscribed Variables");
33559 folderBrowseName = UA_QUALIFIEDNAME(1, "Subscribed Variables");
33560 }
33561
33562 UA_Server_addObjectNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
33563 UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), folderBrowseName,
33564 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), oAttr, NULL, &folderId);
33565 /**
33566 * **TargetVariables**
33567 *
33568 * The SubscribedDataSet option TargetVariables defines a list of Variable
33569 * mappings between received DataSet fields and target Variables in the Subscriber
33570 * AddressSpace. The values subscribed from the Publisher are updated in the value
33571 * field of these variables */
33572 /* Create the TargetVariables with respect to DataSetMetaData fields */
33573 UA_FieldTargetVariable *targetVarsData = (UA_FieldTargetVariable *)
33574 UA_calloc(targetVars->targetVariablesSize, sizeof(UA_FieldTargetVariable));
33575 for(size_t i = 0; i < targetVars->targetVariablesSize; i++) {
33576 /* Variable to subscribe data */
33577 UA_VariableAttributes vAttr = UA_VariableAttributes_default;
33578 UA_LocalizedText_copy(&pMetaData->fields[i].description, &vAttr.description);
33579 vAttr.displayName.locale = UA_STRING("");
33580 vAttr.displayName.text = pMetaData->fields[i].name;
33581 vAttr.dataType = pMetaData->fields[i].dataType;
33582
33583 UA_QualifiedName browseName;
33584 browseName.namespaceIndex = 1;
33585 browseName.name = pMetaData->fields[i].name;
33586
33587 UA_NodeId newNode;
33588 retVal |= UA_Server_addVariableNode(
33589 server, targetVars->targetVariables[i].targetNodeId, folderId,
33590 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), browseName,
33591 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vAttr, NULL, &newNode);
33592
33593 /* For creating Targetvariables */
33594 targetVarsData[i].targetVariable.attributeId =
33595 targetVars->targetVariables[i].attributeId;
33596 targetVarsData[i].targetVariable.targetNodeId = newNode;
33597 }
33598 retVal =
33599 UA_Server_DataSetReader_createTargetVariables(server, dataSetReaderId,
33600 targetVars->targetVariablesSize, targetVarsData);
33601 for(size_t j = 0; j < targetVars->targetVariablesSize; j++)
33602 UA_FieldTargetDataType_clear(&targetVarsData[j].targetVariable);
33603 UA_free(targetVarsData);
33604
33605 return retVal;
33606}
33607
33608/**
33609 * **DataSetReader**
33610 *
33611 * DataSetReader can receive NetworkMessages with the DataSetMessage
33612 * of interest sent by the Publisher. DataSetReader provides
33613 * the configuration necessary to receive and process DataSetMessages
33614 * on the Subscriber side. DataSetReader must be linked with a
33615 * SubscribedDataSet and be contained within a ReaderGroup. */
33616/* Add DataSetReader to the ReaderGroup */
33617static UA_StatusCode
33618addDataSetReaderConfig(UA_Server *server, UA_NodeId readerGroupId,
33619 UA_DataSetReaderDataType *dataSetReaderDataType,
33620 UA_NodeId *dataSetReaderId) {
33621 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33622 UA_DataSetReaderConfig readerConfig;
33623 memset (&readerConfig, 0, sizeof(UA_DataSetReaderConfig));
33624 readerConfig.name = dataSetReaderDataType->name;
33625 /* Parameters to filter which DataSetMessage has to be processed
33626 * by the DataSetReader */
33627 if(dataSetReaderDataType->publisherId.type == &UA_TYPES[UA_TYPES_STRING]){
33628 UA_String publisherIdentifier;
33629 readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_STRING];
33630 UA_String_copy((UA_String *) dataSetReaderDataType->publisherId.data, &publisherIdentifier);
33631 readerConfig.publisherId.data = &publisherIdentifier;
33632 } else {
33633 UA_UInt16 publisherIdentifier = *(UA_UInt16*)dataSetReaderDataType->publisherId.data;
33634 readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_UINT16];
33635 readerConfig.publisherId.data = &publisherIdentifier;
33636 }
33637
33638 readerConfig.writerGroupId = dataSetReaderDataType->writerGroupId;
33639 readerConfig.dataSetWriterId = dataSetReaderDataType->dataSetWriterId;
33640
33641 /* Setting up Meta data configuration in DataSetReader */
33642 UA_DataSetMetaDataType *pMetaData;
33643 pMetaData = &readerConfig.dataSetMetaData;
33644 UA_DataSetMetaDataType_init (pMetaData);
33645 pMetaData->name = dataSetReaderDataType->dataSetMetaData.name;
33646 pMetaData->fieldsSize = dataSetReaderDataType->dataSetMetaData.fieldsSize;
33647 pMetaData->fields = (UA_FieldMetaData*)UA_Array_new (pMetaData->fieldsSize,
33648 &UA_TYPES[UA_TYPES_FIELDMETADATA]);
33649 for(size_t i = 0; i < pMetaData->fieldsSize; i++){
33650 UA_FieldMetaData_init (&pMetaData->fields[i]);
33651 UA_NodeId_copy (&dataSetReaderDataType->dataSetMetaData.fields[i].dataType,
33652 &pMetaData->fields[i].dataType);
33653 pMetaData->fields[i].builtInType = dataSetReaderDataType->dataSetMetaData.fields[i].builtInType;
33654 pMetaData->fields[i].name = dataSetReaderDataType->dataSetMetaData.fields[i].name;
33655 pMetaData->fields[i].valueRank = dataSetReaderDataType->dataSetMetaData.fields[i].valueRank;
33656 }
33657
33658 retVal |= UA_Server_addDataSetReader(server, readerGroupId, &readerConfig,
33659 dataSetReaderId);
33660 if(retVal != UA_STATUSCODE_GOOD) {
33661 UA_free(pMetaData->fields);
33662 return retVal;
33663 }
33664
33665 retVal |= addSubscribedVariables(server, *dataSetReaderId, dataSetReaderDataType, pMetaData);
33666 UA_free(pMetaData->fields);
33667 return retVal;
33668}
33669#endif
33670
33671/*************************************************/
33672/* PubSubConnection */
33673/*************************************************/
33674UA_StatusCode
33675addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection) {
33676 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33677 if(connection->config->name.length > 512)
33678 return UA_STATUSCODE_BADOUTOFMEMORY;
33679 char connectionName[513];
33680 memcpy(connectionName, connection->config->name.data, connection->config->name.length);
33681 connectionName[connection->config->name.length] = '\0';
33682
33683 UA_ObjectAttributes attr = UA_ObjectAttributes_default;
33684 attr.displayName = UA_LOCALIZEDTEXT("", connectionName);
33685 retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
33686 UA_NODEID_NUMERIC(1, 0), /* Generate a new id */
33687 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
33688 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPUBSUBCONNECTION),
33689 UA_QUALIFIEDNAME(0, connectionName),
33690 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE),
33691 (const UA_NodeAttributes*)&attr,
33692 &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
33693 NULL, &connection->identifier);
33694
33695 attr.displayName = UA_LOCALIZEDTEXT("", "Address");
33696 retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
33697 connection->identifier,
33698 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33699 UA_QUALIFIEDNAME(0, "Address"),
33700 UA_NODEID_NUMERIC(0, UA_NS0ID_NETWORKADDRESSURLTYPE),
33701 attr, NULL, NULL);
33702
33703 UA_Server_addNode_finish(server, connection->identifier);
33704
33705 UA_NodeId addressNode, urlNode, interfaceNode, publisherIdNode,
33706 connectionPropertieNode, transportProfileUri;
33707 addressNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Address"),
33708 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33709 connection->identifier);
33710 urlNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Url"),
33711 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33712 addressNode);
33713 interfaceNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "NetworkInterface"),
33714 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33715 addressNode);
33716 publisherIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
33717 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33718 connection->identifier);
33719 connectionPropertieNode = findSingleChildNode(server,
33720 UA_QUALIFIEDNAME(0, "ConnectionProperties"),
33721 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33722 connection->identifier);
33723 transportProfileUri = findSingleChildNode(server,
33724 UA_QUALIFIEDNAME(0, "TransportProfileUri"),
33725 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33726 connection->identifier);
33727
33728 if(UA_NodeId_isNull(&addressNode) || UA_NodeId_isNull(&urlNode) ||
33729 UA_NodeId_isNull(&interfaceNode) || UA_NodeId_isNull(&publisherIdNode) ||
33730 UA_NodeId_isNull(&connectionPropertieNode) ||
33731 UA_NodeId_isNull(&transportProfileUri)) {
33732 return UA_STATUSCODE_BADNOTFOUND;
33733 }
33734
33735 retVal |= writePubSubNs0VariableArray(server, connectionPropertieNode.identifier.numeric,
33736 connection->config->connectionProperties,
33737 connection->config->connectionPropertiesSize,
33738 &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
33739
33740 UA_NetworkAddressUrlDataType *networkAddressUrlDataType =
33741 ((UA_NetworkAddressUrlDataType*)connection->config->address.data);
33742 UA_Variant value;
33743 UA_Variant_init(&value);
33744 UA_Variant_setScalar(&value, &networkAddressUrlDataType->url,
33745 &UA_TYPES[UA_TYPES_STRING]);
33746 UA_Server_writeValue(server, urlNode, value);
33747 UA_Variant_setScalar(&value, &networkAddressUrlDataType->networkInterface,
33748 &UA_TYPES[UA_TYPES_STRING]);
33749 UA_Server_writeValue(server, interfaceNode, value);
33750 UA_Variant_setScalar(&value, &connection->config->transportProfileUri,
33751 &UA_TYPES[UA_TYPES_STRING]);
33752 UA_Server_writeValue(server, transportProfileUri, value);
33753
33754 UA_NodePropertyContext *connectionPublisherIdContext = (UA_NodePropertyContext *)
33755 UA_malloc(sizeof(UA_NodePropertyContext));
33756 connectionPublisherIdContext->parentNodeId = connection->identifier;
33757 connectionPublisherIdContext->parentClassifier = UA_NS0ID_PUBSUBCONNECTIONTYPE;
33758 connectionPublisherIdContext->elementClassiefier =
33759 UA_NS0ID_PUBSUBCONNECTIONTYPE_PUBLISHERID;
33760 UA_ValueCallback valueCallback;
33761 valueCallback.onRead = onRead;
33762 valueCallback.onWrite = NULL;
33763 retVal |= addVariableValueSource(server, valueCallback, publisherIdNode,
33764 connectionPublisherIdContext);
33765
33766#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33767 retVal |= UA_Server_addReference(server, connection->identifier,
33768 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33769 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP),
33770 true);
33771 retVal |= UA_Server_addReference(server, connection->identifier,
33772 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33773 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP),
33774 true);
33775 retVal |= UA_Server_addReference(server, connection->identifier,
33776 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33777 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP),
33778 true);
33779#endif
33780 return retVal;
33781}
33782
33783#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33784static UA_StatusCode
33785addPubSubConnectionAction(UA_Server *server,
33786 const UA_NodeId *sessionId, void *sessionHandle,
33787 const UA_NodeId *methodId, void *methodContext,
33788 const UA_NodeId *objectId, void *objectContext,
33789 size_t inputSize, const UA_Variant *input,
33790 size_t outputSize, UA_Variant *output){
33791 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33792 UA_PubSubConnectionDataType pubSubConnectionDataType = *((UA_PubSubConnectionDataType *) input[0].data);
33793
33794 //call API function and create the connection
33795 UA_NodeId connectionId;
33796 retVal |= addPubSubConnectionConfig(server, &pubSubConnectionDataType, &connectionId);
33797 if(retVal != UA_STATUSCODE_GOOD) {
33798 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addPubSubConnection failed");
33799 return retVal;
33800 }
33801
33802 for(size_t i = 0; i < pubSubConnectionDataType.writerGroupsSize; i++){
33803 UA_NodeId writerGroupId;
33804 UA_WriterGroupDataType *writerGroupDataType = &pubSubConnectionDataType.writerGroups[i];
33805 retVal |= addWriterGroupConfig(server, connectionId, writerGroupDataType, &writerGroupId);
33806 if(retVal != UA_STATUSCODE_GOOD) {
33807 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addWriterGroup failed");
33808 return retVal;
33809 }
33810
33811 for (size_t j = 0; j < pubSubConnectionDataType.writerGroups[i].dataSetWritersSize; j++){
33812 UA_DataSetWriterDataType *dataSetWriterDataType = &writerGroupDataType->dataSetWriters[j];
33813 retVal |= addDataSetWriterConfig(server, &writerGroupId, dataSetWriterDataType, NULL);
33814 if(retVal != UA_STATUSCODE_GOOD) {
33815 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetWriter failed");
33816 return retVal;
33817 }
33818 }
33819
33820 //TODO: Need to handle the UA_Server_setWriterGroupOperational based on the status variable in information model
33821 if(pubSubConnectionDataType.enabled) {
33822 UA_Server_freezeWriterGroupConfiguration(server, writerGroupId);
33823 UA_Server_setWriterGroupOperational(server, writerGroupId);
33824 } else
33825 UA_Server_setWriterGroupDisabled(server, writerGroupId);
33826 }
33827
33828 for(size_t i = 0; i < pubSubConnectionDataType.readerGroupsSize; i++){
33829 UA_NodeId readerGroupId;
33830 UA_ReaderGroupDataType *rg = &pubSubConnectionDataType.readerGroups[i];
33831 retVal |= addReaderGroupConfig(server, connectionId, rg, &readerGroupId);
33832 if(retVal != UA_STATUSCODE_GOOD) {
33833 UA_NodeId_clear(&readerGroupId);
33834 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addReaderGroup failed");
33835 return retVal;
33836 }
33837
33838 for(size_t j = 0; j < rg->dataSetReadersSize; j++) {
33839 UA_NodeId dataSetReaderId;
33840 UA_DataSetReaderDataType *dataSetReaderDataType = &rg->dataSetReaders[j];
33841 retVal |= addDataSetReaderConfig(server, readerGroupId, dataSetReaderDataType, &dataSetReaderId);
33842 if(retVal != UA_STATUSCODE_GOOD) {
33843 UA_NodeId_clear(&readerGroupId);
33844 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetReader failed");
33845 return retVal;
33846 }
33847 }
33848
33849 //TODO: Need to handle the UA_Server_setReaderGroupOperational based on the status variable in information model
33850 if(pubSubConnectionDataType.enabled) {
33851 UA_Server_freezeReaderGroupConfiguration(server, readerGroupId);
33852 UA_Server_setReaderGroupOperational(server, readerGroupId);
33853 } else {
33854 UA_Server_setReaderGroupDisabled(server, readerGroupId);
33855 }
33856
33857 UA_NodeId_clear(&readerGroupId);
33858 }
33859 //set ouput value
33860 UA_Variant_setScalarCopy(output, &connectionId, &UA_TYPES[UA_TYPES_NODEID]);
33861 return UA_STATUSCODE_GOOD;
33862}
33863#endif
33864
33865UA_StatusCode
33866removePubSubConnectionRepresentation(UA_Server *server,
33867 UA_PubSubConnection *connection) {
33868 return UA_Server_deleteNode(server, connection->identifier, true);
33869}
33870
33871#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33872static UA_StatusCode
33873removeConnectionAction(UA_Server *server,
33874 const UA_NodeId *sessionId, void *sessionHandle,
33875 const UA_NodeId *methodId, void *methodContext,
33876 const UA_NodeId *objectId, void *objectContext,
33877 size_t inputSize, const UA_Variant *input,
33878 size_t outputSize, UA_Variant *output){
33879 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33880 UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
33881 retVal |= UA_Server_removePubSubConnection(server, nodeToRemove);
33882 if(retVal == UA_STATUSCODE_BADNOTFOUND)
33883 retVal = UA_STATUSCODE_BADNODEIDUNKNOWN;
33884 return retVal;
33885}
33886#endif
33887
33888/**********************************************/
33889/* DataSetReader */
33890/**********************************************/
33891UA_StatusCode
33892addDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReader){
33893 if(dataSetReader->config.name.length > 512)
33894 return UA_STATUSCODE_BADCONFIGURATIONERROR;
33895
33896 char dsrName[513];
33897 memcpy(dsrName, dataSetReader->config.name.data, dataSetReader->config.name.length);
33898 dsrName[dataSetReader->config.name.length] = '\0';
33899
33900 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33901 UA_NodeId publisherIdNode, writerGroupIdNode, dataSetwriterIdNode;
33902
33903 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
33904 object_attr.displayName = UA_LOCALIZEDTEXT("", dsrName);
33905 retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
33906 dataSetReader->linkedReaderGroup,
33907 UA_NODEID_NUMERIC(0, UA_NS0ID_HASDATASETREADER),
33908 UA_QUALIFIEDNAME(0, dsrName),
33909 UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETREADERTYPE),
33910 object_attr, NULL, &dataSetReader->identifier);
33911
33912 /* Add childNodes such as PublisherId, WriterGroupId and DataSetWriterId in
33913 * DataSetReader object */
33914 publisherIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
33915 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33916 dataSetReader->identifier);
33917 writerGroupIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "WriterGroupId"),
33918 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33919 dataSetReader->identifier);
33920 dataSetwriterIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
33921 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33922 dataSetReader->identifier);
33923
33924 if(UA_NodeId_isNull(&publisherIdNode) ||
33925 UA_NodeId_isNull(&writerGroupIdNode) ||
33926 UA_NodeId_isNull(&dataSetwriterIdNode)) {
33927 return UA_STATUSCODE_BADNOTFOUND;
33928 }
33929
33930 UA_NodePropertyContext *dataSetReaderPublisherIdContext =
33931 (UA_NodePropertyContext *) UA_malloc(sizeof(UA_NodePropertyContext));
33932 dataSetReaderPublisherIdContext->parentNodeId = dataSetReader->identifier;
33933 dataSetReaderPublisherIdContext->parentClassifier = UA_NS0ID_DATASETREADERTYPE;
33934 dataSetReaderPublisherIdContext->elementClassiefier = UA_NS0ID_DATASETREADERTYPE_PUBLISHERID;
33935 UA_ValueCallback valueCallback;
33936 valueCallback.onRead = onRead;
33937 valueCallback.onWrite = NULL;
33938 retVal |= addVariableValueSource(server, valueCallback, publisherIdNode,
33939 dataSetReaderPublisherIdContext);
33940
33941 /* Update childNode with values from Publisher */
33942 UA_Variant value;
33943 UA_Variant_init(&value);
33944 UA_Variant_setScalar(&value, &dataSetReader->config.writerGroupId,
33945 &UA_TYPES[UA_TYPES_UINT16]);
33946 UA_Server_writeValue(server, writerGroupIdNode, value);
33947 UA_Variant_setScalar(&value, &dataSetReader->config.dataSetWriterId,
33948 &UA_TYPES[UA_TYPES_UINT16]);
33949 UA_Server_writeValue(server, dataSetwriterIdNode, value);
33950 return retVal;
33951}
33952
33953#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33954static UA_StatusCode
33955addDataSetReaderAction(UA_Server *server,
33956 const UA_NodeId *sessionId, void *sessionHandle,
33957 const UA_NodeId *methodId, void *methodContext,
33958 const UA_NodeId *objectId, void *objectContext,
33959 size_t inputSize, const UA_Variant *input,
33960 size_t outputSize, UA_Variant *output){
33961 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33962 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, *objectId);
33963 if(rg->configurationFrozen) {
33964 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33965 "addDataSetReader cannot be done because ReaderGroup config frozen");
33966 return UA_STATUSCODE_BAD;
33967 }
33968
33969 UA_NodeId dataSetReaderId;
33970 UA_DataSetReaderDataType *dataSetReaderDataType = (UA_DataSetReaderDataType *) input[0].data;
33971 retVal |= addDataSetReaderConfig(server, *objectId, dataSetReaderDataType, &dataSetReaderId);
33972 if(retVal != UA_STATUSCODE_GOOD) {
33973 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetReader failed");
33974 return retVal;
33975 }
33976
33977 UA_Variant_setScalarCopy(output, &dataSetReaderId, &UA_TYPES[UA_TYPES_NODEID]);
33978 return retVal;
33979}
33980#endif
33981
33982UA_StatusCode
33983removeDataSetReaderRepresentation(UA_Server *server,
33984 UA_DataSetReader* dataSetReader) {
33985 return UA_Server_deleteNode(server, dataSetReader->identifier, true);
33986}
33987
33988#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33989static UA_StatusCode
33990removeDataSetReaderAction(UA_Server *server,
33991 const UA_NodeId *sessionId, void *sessionHandle,
33992 const UA_NodeId *methodId, void *methodContext,
33993 const UA_NodeId *objectId, void *objectContext,
33994 size_t inputSize, const UA_Variant *input,
33995 size_t outputSize, UA_Variant *output){
33996 UA_NodeId nodeToRemove = *((UA_NodeId *)input[0].data);
33997 return UA_Server_removeDataSetReader(server, nodeToRemove);
33998}
33999#endif
34000
34001/*************************************************/
34002/* PublishedDataSet */
34003/*************************************************/
34004#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34005static UA_StatusCode
34006addDataSetFolderAction(UA_Server *server,
34007 const UA_NodeId *sessionId, void *sessionHandle,
34008 const UA_NodeId *methodId, void *methodContext,
34009 const UA_NodeId *objectId, void *objectContext,
34010 size_t inputSize, const UA_Variant *input,
34011 size_t outputSize, UA_Variant *output){
34012 /* defined in R 1.04 9.1.4.5.7 */
34013 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34014 UA_String newFolderName = *((UA_String *) input[0].data);
34015 UA_NodeId generatedId;
34016 UA_ObjectAttributes objectAttributes = UA_ObjectAttributes_default;
34017 UA_LocalizedText name = {UA_STRING(""), newFolderName};
34018 objectAttributes.displayName = name;
34019 retVal |= UA_Server_addObjectNode(server, UA_NODEID_NULL, *objectId,
34020 UA_NODEID_NUMERIC(0,UA_NS0ID_ORGANIZES),
34021 UA_QUALIFIEDNAME(0, "DataSetFolder"),
34022 UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE),
34023 objectAttributes, NULL, &generatedId);
34024 UA_Variant_setScalarCopy(output, &generatedId, &UA_TYPES[UA_TYPES_NODEID]);
34025#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34026 retVal |= UA_Server_addReference(server, generatedId,
34027 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34028 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), true);
34029 retVal |= UA_Server_addReference(server, generatedId,
34030 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34031 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), true);
34032 retVal |= UA_Server_addReference(server, generatedId,
34033 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34034 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), true);
34035 retVal |= UA_Server_addReference(server, generatedId,
34036 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34037 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), true);
34038#endif
34039 return retVal;
34040}
34041#endif
34042
34043#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34044static UA_StatusCode
34045removeDataSetFolderAction(UA_Server *server,
34046 const UA_NodeId *sessionId, void *sessionHandle,
34047 const UA_NodeId *methodId, void *methodContext,
34048 const UA_NodeId *objectId, void *objectContext,
34049 size_t inputSize, const UA_Variant *input,
34050 size_t outputSize, UA_Variant *output) {
34051 UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
34052 return UA_Server_deleteNode(server, nodeToRemove, true);
34053}
34054#endif
34055
34056UA_StatusCode
34057addPublishedDataItemsRepresentation(UA_Server *server,
34058 UA_PublishedDataSet *publishedDataSet) {
34059 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34060 if(publishedDataSet->config.name.length > 512)
34061 return UA_STATUSCODE_BADOUTOFMEMORY;
34062 char pdsName[513];
34063 memcpy(pdsName, publishedDataSet->config.name.data, publishedDataSet->config.name.length);
34064 pdsName[publishedDataSet->config.name.length] = '\0';
34065
34066 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
34067 object_attr.displayName = UA_LOCALIZEDTEXT("", pdsName);
34068 retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* Create a new id */
34069 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34070 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34071 UA_QUALIFIEDNAME(0, pdsName),
34072 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE),
34073 object_attr, NULL, &publishedDataSet->identifier);
34074 UA_CHECK_STATUS(retVal, return retVal);
34075
34076 UA_ValueCallback valueCallback;
34077 valueCallback.onRead = onRead;
34078 valueCallback.onWrite = NULL;
34079 //ToDo: Need to move the browse name from namespaceindex 0 to 1
34080 UA_NodeId configurationVersionNode =
34081 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "ConfigurationVersion"),
34082 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34083 publishedDataSet->identifier);
34084 if(UA_NodeId_isNull(&configurationVersionNode))
34085 return UA_STATUSCODE_BADNOTFOUND;
34086
34087 UA_NodePropertyContext *configurationVersionContext = (UA_NodePropertyContext *)
34088 UA_malloc(sizeof(UA_NodePropertyContext));
34089 configurationVersionContext->parentNodeId = publishedDataSet->identifier;
34090 configurationVersionContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE;
34091 configurationVersionContext->elementClassiefier =
34092 UA_NS0ID_PUBLISHEDDATAITEMSTYPE_CONFIGURATIONVERSION;
34093 retVal |= addVariableValueSource(server, valueCallback, configurationVersionNode,
34094 configurationVersionContext);
34095
34096 UA_NodeId publishedDataNode =
34097 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishedData"),
34098 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34099 publishedDataSet->identifier);
34100 if(UA_NodeId_isNull(&publishedDataNode))
34101 return UA_STATUSCODE_BADNOTFOUND;
34102
34103 UA_NodePropertyContext * publishingIntervalContext = (UA_NodePropertyContext *)
34104 UA_malloc(sizeof(UA_NodePropertyContext));
34105 publishingIntervalContext->parentNodeId = publishedDataSet->identifier;
34106 publishingIntervalContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE;
34107 publishingIntervalContext->elementClassiefier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE_PUBLISHEDDATA;
34108 retVal |= addVariableValueSource(server, valueCallback, publishedDataNode,
34109 publishingIntervalContext);
34110
34111 UA_NodeId dataSetMetaDataNode =
34112 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetMetaData"),
34113 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34114 publishedDataSet->identifier);
34115 if(UA_NodeId_isNull(&dataSetMetaDataNode))
34116 return UA_STATUSCODE_BADNOTFOUND;
34117
34118 UA_NodePropertyContext *metaDataContext = (UA_NodePropertyContext *)
34119 UA_malloc(sizeof(UA_NodePropertyContext));
34120 metaDataContext->parentNodeId = publishedDataSet->identifier;
34121 metaDataContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE;
34122 metaDataContext->elementClassiefier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE_DATASETMETADATA;
34123 retVal |= addVariableValueSource(server, valueCallback,
34124 dataSetMetaDataNode, metaDataContext);
34125
34126#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34127 retVal |= UA_Server_addReference(server, publishedDataSet->identifier,
34128 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34129 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_ADDVARIABLES), true);
34130 retVal |= UA_Server_addReference(server, publishedDataSet->identifier,
34131 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34132 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_REMOVEVARIABLES), true);
34133#endif
34134 return retVal;
34135}
34136
34137#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34138static UA_StatusCode
34139addPublishedDataItemsAction(UA_Server *server,
34140 const UA_NodeId *sessionId, void *sessionHandle,
34141 const UA_NodeId *methodId, void *methodContext,
34142 const UA_NodeId *objectId, void *objectContext,
34143 size_t inputSize, const UA_Variant *input,
34144 size_t outputSize, UA_Variant *output){
34145 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34146 size_t fieldNameAliasesSize = input[1].arrayLength;
34147 UA_String * fieldNameAliases = (UA_String *) input[1].data;
34148 size_t fieldFlagsSize = input[2].arrayLength;
34149 UA_DataSetFieldFlags * fieldFlags = (UA_DataSetFieldFlags *) input[2].data;
34150 size_t variablesToAddSize = input[3].arrayLength;
34151 UA_PublishedVariableDataType *variablesToAdd = NULL;
34152 UA_ExtensionObject *eoAddVar = NULL;
34153 if(input[3].type == &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE])
34154 variablesToAdd = (UA_PublishedVariableDataType*)input[3].data;
34155 else if(input[3].type == &UA_TYPES[UA_TYPES_EXTENSIONOBJECT])
34156 eoAddVar = (UA_ExtensionObject *)input[3].data;
34157 else
34158 return UA_STATUSCODE_BADINTERNALERROR;
34159
34160 if(!(fieldNameAliasesSize == fieldFlagsSize || fieldFlagsSize == variablesToAddSize))
34161 return UA_STATUSCODE_BADINVALIDARGUMENT;
34162
34163 UA_PublishedDataSetConfig publishedDataSetConfig;
34164 memset(&publishedDataSetConfig, 0, sizeof(publishedDataSetConfig));
34165 publishedDataSetConfig.name = *((UA_String *) input[0].data);
34166 publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
34167
34168 UA_NodeId dataSetItemsNodeId;
34169 retVal |= UA_Server_addPublishedDataSet(server, &publishedDataSetConfig,
34170 &dataSetItemsNodeId).addResult;
34171 if(retVal != UA_STATUSCODE_GOOD) {
34172 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34173 "addPublishedDataset failed");
34174 return retVal;
34175 }
34176
34177 UA_DataSetFieldConfig dataSetFieldConfig;
34178 for(size_t j = 0; j < variablesToAddSize; ++j) {
34179 /* Prepare the config */
34180 memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig));
34181 dataSetFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
34182 dataSetFieldConfig.field.variable.fieldNameAlias = fieldNameAliases[j];
34183 if(fieldFlags[j] == UA_DATASETFIELDFLAGS_PROMOTEDFIELD)
34184 dataSetFieldConfig.field.variable.promotedField = true;
34185
34186 UA_PublishedVariableDataType *variableToAdd;
34187 if(variablesToAdd) {
34188 variableToAdd = &variablesToAdd[j];
34189 } else {
34190 if(eoAddVar[j].content.decoded.type !=
34191 &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE])
34192 return UA_STATUSCODE_BADINTERNALERROR;
34193 variableToAdd = (UA_PublishedVariableDataType*)
34194 eoAddVar[j].content.decoded.data;
34195 }
34196 dataSetFieldConfig.field.variable.publishParameters = *variableToAdd;
34197
34198 /* Add the dataset field */
34199 retVal |= UA_Server_addDataSetField(server, dataSetItemsNodeId,
34200 &dataSetFieldConfig, NULL).result;
34201 if(retVal != UA_STATUSCODE_GOOD) {
34202 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34203 "addDataSetField failed");
34204 return retVal;
34205 }
34206 }
34207
34208 UA_Variant_setScalarCopy(output, &dataSetItemsNodeId, &UA_TYPES[UA_TYPES_NODEID]);
34209 return retVal;
34210}
34211#endif
34212
34213#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34214static UA_StatusCode
34215addVariablesAction(UA_Server *server,
34216 const UA_NodeId *sessionId, void *sessionHandle,
34217 const UA_NodeId *methodId, void *methodContext,
34218 const UA_NodeId *objectId, void *objectContext,
34219 size_t inputSize, const UA_Variant *input,
34220 size_t outputSize, UA_Variant *output){
34221 return UA_STATUSCODE_GOOD;
34222}
34223
34224static UA_StatusCode
34225removeVariablesAction(UA_Server *server,
34226 const UA_NodeId *sessionId, void *sessionHandle,
34227 const UA_NodeId *methodId, void *methodContext,
34228 const UA_NodeId *objectId, void *objectContext,
34229 size_t inputSize, const UA_Variant *input,
34230 size_t outputSize, UA_Variant *output){
34231 return UA_STATUSCODE_GOOD;
34232}
34233#endif
34234
34235
34236UA_StatusCode
34237removePublishedDataSetRepresentation(UA_Server *server,
34238 UA_PublishedDataSet *publishedDataSet) {
34239 return UA_Server_deleteNode(server, publishedDataSet->identifier, true);
34240}
34241
34242#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34243static UA_StatusCode
34244removePublishedDataSetAction(UA_Server *server,
34245 const UA_NodeId *sessionId, void *sessionHandle,
34246 const UA_NodeId *methodId, void *methodContext,
34247 const UA_NodeId *objectId, void *objectContext,
34248 size_t inputSize, const UA_Variant *input,
34249 size_t outputSize, UA_Variant *output){
34250 UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
34251 return UA_Server_removePublishedDataSet(server, nodeToRemove);
34252}
34253#endif
34254
34255/**********************************************/
34256/* WriterGroup */
34257/**********************************************/
34258
34259static UA_StatusCode
34260readContentMask(UA_Server *server, const UA_NodeId *sessionId,
34261 void *sessionContext, const UA_NodeId *nodeId,
34262 void *nodeContext, UA_Boolean includeSourceTimeStamp,
34263 const UA_NumericRange *range, UA_DataValue *value) {
34264 UA_WriterGroup *writerGroup = (UA_WriterGroup*)nodeContext;
34265 if((writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED &&
34266 writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) ||
34267 writerGroup->config.messageSettings.content.decoded.type !=
34268 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])
34269 return UA_STATUSCODE_BADINTERNALERROR;
34270 UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*)
34271 writerGroup->config.messageSettings.content.decoded.data;
34272
34273 UA_Variant_setScalarCopy(&value->value, &wgm->networkMessageContentMask,
34274 &UA_TYPES[UA_TYPES_UADPNETWORKMESSAGECONTENTMASK]);
34275 value->hasValue = true;
34276 return UA_STATUSCODE_GOOD;
34277}
34278
34279static UA_StatusCode
34280writeContentMask(UA_Server *server, const UA_NodeId *sessionId,
34281 void *sessionContext, const UA_NodeId *nodeId,
34282 void *nodeContext, const UA_NumericRange *range,
34283 const UA_DataValue *value) {
34284 UA_WriterGroup *writerGroup = (UA_WriterGroup*)nodeContext;
34285 if((writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED &&
34286 writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) ||
34287 writerGroup->config.messageSettings.content.decoded.type !=
34288 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])
34289 return UA_STATUSCODE_BADINTERNALERROR;
34290 UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*)
34291 writerGroup->config.messageSettings.content.decoded.data;
34292
34293 if(!value->value.type)
34294 return UA_STATUSCODE_BADTYPEMISMATCH;
34295 if(value->value.type->typeKind != UA_DATATYPEKIND_ENUM &&
34296 value->value.type->typeKind != UA_DATATYPEKIND_INT32)
34297 return UA_STATUSCODE_BADTYPEMISMATCH;
34298
34299 wgm->networkMessageContentMask = *(UA_UadpNetworkMessageContentMask*)value->value.data;
34300 return UA_STATUSCODE_GOOD;
34301}
34302
34303UA_StatusCode
34304addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup){
34305 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34306 if(writerGroup->config.name.length > 512)
34307 return UA_STATUSCODE_BADOUTOFMEMORY;
34308 char wgName[513];
34309 memcpy(wgName, writerGroup->config.name.data, writerGroup->config.name.length);
34310 wgName[writerGroup->config.name.length] = '\0';
34311
34312 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
34313 object_attr.displayName = UA_LOCALIZEDTEXT("", wgName);
34314 retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create a new id */
34315 writerGroup->linkedConnection->identifier,
34316 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34317 UA_QUALIFIEDNAME(0, wgName),
34318 UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE),
34319 object_attr, NULL, &writerGroup->identifier);
34320
34321 UA_NodeId keepAliveNode =
34322 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "KeepAliveTime"),
34323 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34324 writerGroup->identifier);
34325 UA_NodeId publishingIntervalNode =
34326 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
34327 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34328 writerGroup->identifier);
34329 if(UA_NodeId_isNull(&keepAliveNode) ||
34330 UA_NodeId_isNull(&publishingIntervalNode))
34331 return UA_STATUSCODE_BADNOTFOUND;
34332
34333 UA_NodePropertyContext * publishingIntervalContext = (UA_NodePropertyContext *)
34334 UA_malloc(sizeof(UA_NodePropertyContext));
34335 publishingIntervalContext->parentNodeId = writerGroup->identifier;
34336 publishingIntervalContext->parentClassifier = UA_NS0ID_WRITERGROUPTYPE;
34337 publishingIntervalContext->elementClassiefier = UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL;
34338 UA_ValueCallback valueCallback;
34339 valueCallback.onRead = onRead;
34340 valueCallback.onWrite = onWrite;
34341 retVal |= addVariableValueSource(server, valueCallback,
34342 publishingIntervalNode, publishingIntervalContext);
34343 UA_Server_writeAccessLevel(server, publishingIntervalNode,
34344 UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE);
34345
34346 UA_NodeId priorityNode =
34347 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Priority"),
34348 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34349 writerGroup->identifier);
34350 UA_NodeId writerGroupIdNode =
34351 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "WriterGroupId"),
34352 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34353 writerGroup->identifier);
34354
34355 UA_Variant value;
34356 UA_Variant_init(&value);
34357 UA_Variant_setScalar(&value, &writerGroup->config.publishingInterval, &UA_TYPES[UA_TYPES_DURATION]);
34358 UA_Server_writeValue(server, publishingIntervalNode, value);
34359 UA_Variant_setScalar(&value, &writerGroup->config.keepAliveTime, &UA_TYPES[UA_TYPES_DURATION]);
34360 UA_Server_writeValue(server, keepAliveNode, value);
34361 UA_Variant_setScalar(&value, &writerGroup->config.priority, &UA_TYPES[UA_TYPES_BYTE]);
34362 UA_Server_writeValue(server, priorityNode, value);
34363 UA_Variant_setScalar(&value, &writerGroup->config.writerGroupId, &UA_TYPES[UA_TYPES_UINT16]);
34364 UA_Server_writeValue(server, writerGroupIdNode, value);
34365
34366 object_attr.displayName = UA_LOCALIZEDTEXT("", "MessageSettings");
34367 retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
34368 writerGroup->identifier,
34369 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34370 UA_QUALIFIEDNAME(0, "MessageSettings"),
34371 UA_NODEID_NUMERIC(0, UA_NS0ID_UADPWRITERGROUPMESSAGETYPE),
34372 object_attr, NULL, NULL);
34373
34374 /* Find the variable with the content mask */
34375
34376 UA_NodeId messageSettingsId =
34377 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "MessageSettings"),
34378 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34379 writerGroup->identifier);
34380 UA_NodeId contentMaskId =
34381 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "NetworkMessageContentMask"),
34382 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), messageSettingsId);
34383 if(!UA_NodeId_isNull(&contentMaskId)) {
34384 /* Set the callback */
34385 UA_DataSource ds;
34386 ds.read = readContentMask;
34387 ds.write = writeContentMask;
34388 UA_Server_setVariableNode_dataSource(server, contentMaskId, ds);
34389 UA_Server_setNodeContext(server, contentMaskId, writerGroup);
34390
34391 /* Make writable */
34392 UA_Server_writeAccessLevel(server, contentMaskId,
34393 UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_READ);
34394
34395 }
34396
34397 /* Add reference to methods */
34398#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34399 retVal |= UA_Server_addReference(server, writerGroup->identifier,
34400 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34401 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), true);
34402 retVal |= UA_Server_addReference(server, writerGroup->identifier,
34403 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34404 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), true);
34405#endif
34406
34407 return retVal;
34408}
34409
34410#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34411static UA_StatusCode
34412addWriterGroupAction(UA_Server *server,
34413 const UA_NodeId *sessionId, void *sessionHandle,
34414 const UA_NodeId *methodId, void *methodContext,
34415 const UA_NodeId *objectId, void *objectContext,
34416 size_t inputSize, const UA_Variant *input,
34417 size_t outputSize, UA_Variant *output){
34418 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34419 UA_WriterGroupDataType *writerGroupDataType = ((UA_WriterGroupDataType *) input[0].data);
34420 UA_NodeId writerGroupId;
34421 retVal |= addWriterGroupConfig(server, *objectId, writerGroupDataType, &writerGroupId);
34422 if(retVal != UA_STATUSCODE_GOOD) {
34423 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addWriterGroup failed");
34424 return retVal;
34425 }
34426 //TODO: Need to handle the UA_Server_setWriterGroupOperational based on the status variable in information model
34427
34428 UA_Variant_setScalarCopy(output, &writerGroupId, &UA_TYPES[UA_TYPES_NODEID]);
34429 return retVal;
34430}
34431#endif
34432
34433UA_StatusCode
34434removeGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup) {
34435 return UA_Server_deleteNode(server, writerGroup->identifier, true);
34436}
34437
34438UA_StatusCode
34439removeReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup) {
34440 return UA_Server_deleteNode(server, readerGroup->identifier, true);
34441}
34442
34443#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34444static UA_StatusCode
34445removeGroupAction(UA_Server *server,
34446 const UA_NodeId *sessionId, void *sessionHandle,
34447 const UA_NodeId *methodId, void *methodContext,
34448 const UA_NodeId *objectId, void *objectContext,
34449 size_t inputSize, const UA_Variant *input,
34450 size_t outputSize, UA_Variant *output){
34451 UA_NodeId nodeToRemove = *((UA_NodeId *)input->data);
34452 if(UA_WriterGroup_findWGbyId(server, nodeToRemove)) {
34453 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, nodeToRemove);
34454 if(wg->configurationFrozen)
34455 UA_Server_unfreezeWriterGroupConfiguration(server, nodeToRemove);
34456 return UA_Server_removeWriterGroup(server, nodeToRemove);
34457 } else {
34458 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, nodeToRemove);
34459 if(rg->configurationFrozen)
34460 UA_Server_unfreezeReaderGroupConfiguration(server, nodeToRemove);
34461 return UA_Server_removeReaderGroup(server, nodeToRemove);
34462 }
34463}
34464#endif
34465
34466/**********************************************/
34467/* ReaderGroup */
34468/**********************************************/
34469
34470UA_StatusCode
34471addReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup) {
34472 if(readerGroup->config.name.length > 512)
34473 return UA_STATUSCODE_BADCONFIGURATIONERROR;
34474 char rgName[513];
34475 memcpy(rgName, readerGroup->config.name.data, readerGroup->config.name.length);
34476 rgName[readerGroup->config.name.length] = '\0';
34477
34478 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
34479 object_attr.displayName = UA_LOCALIZEDTEXT("", rgName);
34480 UA_StatusCode retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
34481 readerGroup->linkedConnection,
34482 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34483 UA_QUALIFIEDNAME(0, rgName),
34484 UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE),
34485 object_attr, NULL, &readerGroup->identifier);
34486#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34487 retVal |= UA_Server_addReference(server, readerGroup->identifier,
34488 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34489 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), true);
34490 retVal |= UA_Server_addReference(server, readerGroup->identifier,
34491 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34492 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), true);
34493#endif
34494 return retVal;
34495}
34496
34497#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34498static UA_StatusCode
34499addReaderGroupAction(UA_Server *server,
34500 const UA_NodeId *sessionId, void *sessionHandle,
34501 const UA_NodeId *methodId, void *methodContext,
34502 const UA_NodeId *objectId, void *objectContext,
34503 size_t inputSize, const UA_Variant *input,
34504 size_t outputSize, UA_Variant *output){
34505 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34506 UA_ReaderGroupDataType *readerGroupDataType = ((UA_ReaderGroupDataType *) input->data);
34507 UA_NodeId readerGroupId;
34508 retVal |= addReaderGroupConfig(server, *objectId, readerGroupDataType, &readerGroupId);
34509 if(retVal != UA_STATUSCODE_GOOD) {
34510 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addReaderGroup failed");
34511 return retVal;
34512 }
34513 //TODO: Need to handle the UA_Server_setReaderGroupOperational based on the status variable in information model
34514
34515 UA_Variant_setScalarCopy(output, &readerGroupId, &UA_TYPES[UA_TYPES_NODEID]);
34516 return retVal;
34517}
34518#endif
34519
34520/**********************************************/
34521/* DataSetWriter */
34522/**********************************************/
34523
34524UA_StatusCode
34525addDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWriter){
34526 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34527 if(dataSetWriter->config.name.length > 512)
34528 return UA_STATUSCODE_BADOUTOFMEMORY;
34529 char dswName[513];
34530 memcpy(dswName, dataSetWriter->config.name.data, dataSetWriter->config.name.length);
34531 dswName[dataSetWriter->config.name.length] = '\0';
34532
34533 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
34534 object_attr.displayName = UA_LOCALIZEDTEXT("", dswName);
34535 retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
34536 dataSetWriter->linkedWriterGroup,
34537 UA_NODEID_NUMERIC(0, UA_NS0ID_HASDATASETWRITER),
34538 UA_QUALIFIEDNAME(0, dswName),
34539 UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETWRITERTYPE),
34540 object_attr, NULL, &dataSetWriter->identifier);
34541
34542 retVal |= UA_Server_addReference(server, dataSetWriter->connectedDataSet,
34543 UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETTOWRITER),
34544 UA_EXPANDEDNODEID_NODEID(dataSetWriter->identifier),
34545 true);
34546
34547 UA_NodeId dataSetWriterIdNode =
34548 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
34549 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34550 dataSetWriter->identifier);
34551 UA_NodeId keyFrameNode =
34552 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "KeyFrameCount"),
34553 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34554 dataSetWriter->identifier);
34555 UA_NodeId dataSetFieldContentMaskNode =
34556 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetFieldContentMask"),
34557 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34558 dataSetWriter->identifier);
34559
34560 UA_NodePropertyContext *dataSetWriterIdContext = (UA_NodePropertyContext *)
34561 UA_malloc(sizeof(UA_NodePropertyContext));
34562 dataSetWriterIdContext->parentNodeId = dataSetWriter->identifier;
34563 dataSetWriterIdContext->parentClassifier = UA_NS0ID_DATASETWRITERTYPE;
34564 dataSetWriterIdContext->elementClassiefier = UA_NS0ID_DATASETWRITERTYPE_DATASETWRITERID;
34565 UA_ValueCallback valueCallback;
34566 valueCallback.onRead = onRead;
34567 valueCallback.onWrite = NULL;
34568 retVal |= addVariableValueSource(server, valueCallback,
34569 dataSetWriterIdNode, dataSetWriterIdContext);
34570
34571 UA_Variant value;
34572 UA_Variant_init(&value);
34573 UA_Variant_setScalar(&value, &dataSetWriter->config.dataSetWriterId,
34574 &UA_TYPES[UA_TYPES_UINT16]);
34575 UA_Server_writeValue(server, dataSetWriterIdNode, value);
34576 UA_Variant_setScalar(&value, &dataSetWriter->config.keyFrameCount,
34577 &UA_TYPES[UA_TYPES_UINT32]);
34578 UA_Server_writeValue(server, keyFrameNode, value);
34579 UA_Variant_setScalar(&value, &dataSetWriter->config.dataSetFieldContentMask,
34580 &UA_TYPES[UA_TYPES_DATASETFIELDCONTENTMASK]);
34581 UA_Server_writeValue(server, dataSetFieldContentMaskNode, value);
34582
34583 object_attr.displayName = UA_LOCALIZEDTEXT("", "MessageSettings");
34584 retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
34585 dataSetWriter->identifier,
34586 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34587 UA_QUALIFIEDNAME(0, "MessageSettings"),
34588 UA_NODEID_NUMERIC(0, UA_NS0ID_UADPDATASETWRITERMESSAGETYPE),
34589 object_attr, NULL, NULL);
34590 return retVal;
34591}
34592
34593#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34594static UA_StatusCode
34595addDataSetWriterAction(UA_Server *server,
34596 const UA_NodeId *sessionId, void *sessionHandle,
34597 const UA_NodeId *methodId, void *methodContext,
34598 const UA_NodeId *objectId, void *objectContext,
34599 size_t inputSize, const UA_Variant *input,
34600 size_t outputSize, UA_Variant *output){
34601 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34602 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, *objectId);
34603 if(!wg) {
34604 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34605 "Not a WriterGroup");
34606 return UA_STATUSCODE_BAD;
34607 }
34608 if(wg->configurationFrozen) {
34609 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34610 "addDataSetWriter cannot be done because writergroup config frozen");
34611 return UA_STATUSCODE_BAD;
34612 }
34613
34614 UA_NodeId dataSetWriterId;
34615 UA_DataSetWriterDataType *dataSetWriterData = (UA_DataSetWriterDataType *)input->data;
34616 retVal |= addDataSetWriterConfig(server, objectId, dataSetWriterData, &dataSetWriterId);
34617 if(retVal != UA_STATUSCODE_GOOD) {
34618 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34619 "addDataSetWriter failed");
34620 return retVal;
34621 }
34622
34623 UA_Variant_setScalarCopy(output, &dataSetWriterId, &UA_TYPES[UA_TYPES_NODEID]);
34624 return UA_STATUSCODE_GOOD;
34625}
34626#endif
34627
34628
34629UA_StatusCode
34630removeDataSetWriterRepresentation(UA_Server *server,
34631 UA_DataSetWriter *dataSetWriter) {
34632 return UA_Server_deleteNode(server, dataSetWriter->identifier, true);
34633}
34634
34635#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34636static UA_StatusCode
34637removeDataSetWriterAction(UA_Server *server,
34638 const UA_NodeId *sessionId, void *sessionHandle,
34639 const UA_NodeId *methodId, void *methodContext,
34640 const UA_NodeId *objectId, void *objectContext,
34641 size_t inputSize, const UA_Variant *input,
34642 size_t outputSize, UA_Variant *output){
34643 UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
34644 return UA_Server_removeDataSetWriter(server, nodeToRemove);
34645}
34646#endif
34647
34648/**********************************************/
34649/* Destructors */
34650/**********************************************/
34651
34652static void
34653connectionTypeDestructor(UA_Server *server,
34654 const UA_NodeId *sessionId, void *sessionContext,
34655 const UA_NodeId *typeId, void *typeContext,
34656 const UA_NodeId *nodeId, void **nodeContext) {
34657 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34658 "Connection destructor called!");
34659 UA_NodeId publisherIdNode =
34660 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
34661 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34662 UA_NodePropertyContext *ctx;
34663 UA_Server_getNodeContext(server, publisherIdNode, (void **)&ctx);
34664 if(!UA_NodeId_isNull(&publisherIdNode))
34665 UA_free(ctx);
34666}
34667
34668static void
34669writerGroupTypeDestructor(UA_Server *server,
34670 const UA_NodeId *sessionId, void *sessionContext,
34671 const UA_NodeId *typeId, void *typeContext,
34672 const UA_NodeId *nodeId, void **nodeContext) {
34673 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34674 "WriterGroup destructor called!");
34675 UA_NodeId intervalNode =
34676 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
34677 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34678 UA_NodePropertyContext *ctx;
34679 UA_Server_getNodeContext(server, intervalNode, (void **)&ctx);
34680 if(!UA_NodeId_isNull(&intervalNode))
34681 UA_free(ctx);
34682}
34683
34684static void
34685readerGroupTypeDestructor(UA_Server *server,
34686 const UA_NodeId *sessionId, void *sessionContext,
34687 const UA_NodeId *typeId, void *typeContext,
34688 const UA_NodeId *nodeId, void **nodeContext) {
34689 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34690 "ReaderGroup destructor called!");
34691}
34692
34693static void
34694dataSetWriterTypeDestructor(UA_Server *server,
34695 const UA_NodeId *sessionId, void *sessionContext,
34696 const UA_NodeId *typeId, void *typeContext,
34697 const UA_NodeId *nodeId, void **nodeContext) {
34698 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34699 "DataSetWriter destructor called!");
34700 UA_NodeId dataSetWriterIdNode =
34701 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
34702 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34703 UA_NodePropertyContext *ctx;
34704 UA_Server_getNodeContext(server, dataSetWriterIdNode, (void **)&ctx);
34705 if(!UA_NodeId_isNull(&dataSetWriterIdNode))
34706 UA_free(ctx);
34707}
34708
34709static void
34710dataSetReaderTypeDestructor(UA_Server *server,
34711 const UA_NodeId *sessionId, void *sessionContext,
34712 const UA_NodeId *typeId, void *typeContext,
34713 const UA_NodeId *nodeId, void **nodeContext) {
34714 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34715 "DataSetReader destructor called!");
34716
34717 /* Deallocate the memory allocated for publisherId */
34718 UA_NodeId publisherIdNode =
34719 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
34720 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34721 UA_NodePropertyContext *ctx;
34722 UA_Server_getNodeContext(server, publisherIdNode, (void **)&ctx);
34723 if(!UA_NodeId_isNull(&publisherIdNode))
34724 UA_free(ctx);
34725}
34726
34727static void
34728publishedDataItemsTypeDestructor(UA_Server *server,
34729 const UA_NodeId *sessionId, void *sessionContext,
34730 const UA_NodeId *typeId, void *typeContext,
34731 const UA_NodeId *nodeId, void **nodeContext) {
34732 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34733 "PublishedDataItems destructor called!");
34734 void *childContext;
34735 UA_NodeId node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishedData"),
34736 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34737 UA_Server_getNodeContext(server, node, (void**)&childContext);
34738 if(!UA_NodeId_isNull(&node))
34739 UA_free(childContext);
34740
34741 node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "ConfigurationVersion"),
34742 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34743 *nodeId);
34744 UA_Server_getNodeContext(server, node, (void**)&childContext);
34745 if(!UA_NodeId_isNull(&node))
34746 UA_free(childContext);
34747
34748 node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetMetaData"),
34749 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34750 UA_Server_getNodeContext(server, node, (void**)&childContext);
34751 if(!UA_NodeId_isNull(&node))
34752 UA_free(childContext);
34753}
34754
34755/*************************************/
34756/* PubSub configurator */
34757/*************************************/
34758
34759#if defined(UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS) && defined(UA_ENABLE_PUBSUB_FILE_CONFIG)
34760
34761/* Callback function that will be executed when the method "PubSub configurator
34762 * (replace config)" is called. */
34763static UA_StatusCode
34764UA_loadPubSubConfigMethodCallback(UA_Server *server,
34765 const UA_NodeId *sessionId, void *sessionHandle,
34766 const UA_NodeId *methodId, void *methodContext,
34767 const UA_NodeId *objectId, void *objectContext,
34768 size_t inputSize, const UA_Variant *input,
34769 size_t outputSize, UA_Variant *output) {
34770 if(inputSize == 1) {
34771 UA_ByteString *inputStr = (UA_ByteString*)input->data;
34772 return UA_PubSubManager_loadPubSubConfigFromByteString(server, *inputStr);
34773 } else if(inputSize > 1) {
34774 return UA_STATUSCODE_BADTOOMANYARGUMENTS;
34775 } else {
34776 return UA_STATUSCODE_BADARGUMENTSMISSING;
34777 }
34778}
34779
34780/* Adds method node to server. This method is used to load binary files for
34781 * PubSub configuration and delete / replace old PubSub configurations. */
34782static UA_StatusCode
34783UA_addLoadPubSubConfigMethod(UA_Server *server) {
34784 UA_Argument inputArgument;
34785 UA_Argument_init(&inputArgument);
34786 inputArgument.description = UA_LOCALIZEDTEXT("", "PubSub config binfile");
34787 inputArgument.name = UA_STRING("BinFile");
34788 inputArgument.dataType = UA_TYPES[UA_TYPES_BYTESTRING].typeId;
34789 inputArgument.valueRank = UA_VALUERANK_SCALAR;
34790
34791 UA_MethodAttributes configAttr = UA_MethodAttributes_default;
34792 configAttr.description = UA_LOCALIZEDTEXT("","Load binary configuration file");
34793 configAttr.displayName = UA_LOCALIZEDTEXT("","LoadPubSubConfigurationFile");
34794 configAttr.executable = true;
34795 configAttr.userExecutable = true;
34796 return UA_Server_addMethodNode(server, UA_NODEID_NULL,
34797 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
34798 UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
34799 UA_QUALIFIEDNAME(1, "PubSub configuration"),
34800 configAttr, &UA_loadPubSubConfigMethodCallback,
34801 1, &inputArgument, 0, NULL, NULL, NULL);
34802}
34803
34804/* Callback function that will be executed when the method "PubSub configurator
34805 * (delete config)" is called. */
34806static UA_StatusCode
34807UA_deletePubSubConfigMethodCallback(UA_Server *server,
34808 const UA_NodeId *sessionId, void *sessionHandle,
34809 const UA_NodeId *methodId, void *methodContext,
34810 const UA_NodeId *objectId, void *objectContext,
34811 size_t inputSize, const UA_Variant *input,
34812 size_t outputSize, UA_Variant *output) {
34813 UA_PubSubManager_delete(server, &(server->pubSubManager));
34814 return UA_STATUSCODE_GOOD;
34815}
34816
34817/* Adds method node to server. This method is used to delete the current PubSub
34818 * configuration. */
34819static UA_StatusCode
34820UA_addDeletePubSubConfigMethod(UA_Server *server) {
34821 UA_MethodAttributes configAttr = UA_MethodAttributes_default;
34822 configAttr.description = UA_LOCALIZEDTEXT("","Delete current PubSub configuration");
34823 configAttr.displayName = UA_LOCALIZEDTEXT("","DeletePubSubConfiguration");
34824 configAttr.executable = true;
34825 configAttr.userExecutable = true;
34826 return UA_Server_addMethodNode(server, UA_NODEID_NULL,
34827 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
34828 UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
34829 UA_QUALIFIEDNAME(1, "Delete PubSub config"),
34830 configAttr, &UA_deletePubSubConfigMethodCallback,
34831 0, NULL, 0, NULL, NULL, NULL);
34832}
34833
34834#endif /* defined(UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS) && defined(UA_ENABLE_PUBSUB_FILE_CONFIG) */
34835
34836UA_StatusCode
34837UA_Server_initPubSubNS0(UA_Server *server) {
34838 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34839 UA_String profileArray[1];
34840 profileArray[0] = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
34841
34842 retVal |= writePubSubNs0VariableArray(server, UA_NS0ID_PUBLISHSUBSCRIBE_SUPPORTEDTRANSPORTPROFILES,
34843 profileArray, 1, &UA_TYPES[UA_TYPES_STRING]);
34844
34845#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34846 /* Add missing references */
34847 retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34848 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34849 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), true);
34850 retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34851 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34852 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), true);
34853 retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34854 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34855 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), true);
34856 retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34857 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34858 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), true);
34859
34860 /* Set method callbacks */
34861 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION), addPubSubConnectionAction);
34862 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION), removeConnectionAction);
34863 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), addDataSetFolderAction);
34864 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), removeDataSetFolderAction);
34865 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), addPublishedDataItemsAction);
34866 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), removePublishedDataSetAction);
34867 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_ADDVARIABLES), addVariablesAction);
34868 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_REMOVEVARIABLES), removeVariablesAction);
34869 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP), addWriterGroupAction);
34870 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP), addReaderGroupAction);
34871 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP), removeGroupAction);
34872 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), addDataSetWriterAction);
34873 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), removeDataSetWriterAction);
34874 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), addDataSetReaderAction);
34875 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), removeDataSetReaderAction);
34876
34877#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
34878 retVal |= UA_addLoadPubSubConfigMethod(server);
34879 retVal |= UA_addDeletePubSubConfigMethod(server);
34880#endif
34881
34882#else
34883 /* Remove methods */
34884 retVal |= UA_Server_deleteReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
34885 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
34886 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION),
34887 false);
34888 retVal |= UA_Server_deleteReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
34889 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
34890 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION),
34891 false);
34892#endif
34893
34894 /* Set the object-type destructors */
34895 UA_NodeTypeLifecycle lifeCycle;
34896 lifeCycle.constructor = NULL;
34897
34898 lifeCycle.destructor = connectionTypeDestructor;
34899 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE), lifeCycle);
34900
34901 lifeCycle.destructor = writerGroupTypeDestructor;
34902 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE), lifeCycle);
34903
34904 lifeCycle.destructor = readerGroupTypeDestructor;
34905 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE), lifeCycle);
34906
34907 lifeCycle.destructor = dataSetWriterTypeDestructor;
34908 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETWRITERTYPE), lifeCycle);
34909
34910 lifeCycle.destructor = publishedDataItemsTypeDestructor;
34911 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE), lifeCycle);
34912
34913 lifeCycle.destructor = dataSetReaderTypeDestructor;
34914 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETREADERTYPE), lifeCycle);
34915
34916 return retVal;
34917}
34918
34919#endif /* UA_ENABLE_PUBSUB_INFORMATIONMODEL */
34920
34921/**** amalgamated original file "/src/server/ua_services_view.c" ****/
34922
34923/* This Source Code Form is subject to the terms of the Mozilla Public
34924 * License, v. 2.0. If a copy of the MPL was not distributed with this
34925 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
34926 *
34927 * Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
34928 * Copyright 2014-2017 (c) Florian Palm
34929 * Copyright 2015-2016 (c) Sten Grüner
34930 * Copyright 2015 (c) LEvertz
34931 * Copyright 2015 (c) Chris Iatrou
34932 * Copyright 2015 (c) Ecosmos
34933 * Copyright 2015-2016 (c) Oleksiy Vasylyev
34934 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
34935 * Copyright 2016 (c) Lorenz Haas
34936 * Copyright 2017 (c) pschoppe
34937 * Copyright 2017 (c) Julian Grothoff
34938 * Copyright 2017 (c) Henrik Norrman
34939 */
34940
34941
34942#define UA_MAX_TREE_RECURSE 50 /* How deep up/down the tree do we recurse at most? */
34943
34944UA_StatusCode
34945referenceTypeIndices(UA_Server *server, const UA_NodeId *refType,
34946 UA_ReferenceTypeSet *indices, UA_Boolean includeSubtypes) {
34947 if(UA_NodeId_isNull(p: refType)) {
34948 UA_ReferenceTypeSet_any(set: indices);
34949 return UA_STATUSCODE_GOOD;
34950 }
34951
34952 UA_ReferenceTypeSet_init(set: indices);
34953 const UA_Node *refNode = UA_NODESTORE_GET(server, refType);
34954 if(!refNode)
34955 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
34956
34957 if(refNode->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
34958 UA_NODESTORE_RELEASE(server, refNode);
34959 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
34960 }
34961
34962 if(!includeSubtypes)
34963 *indices = UA_REFTYPESET(index: refNode->referenceTypeNode.referenceTypeIndex);
34964 else
34965 *indices = refNode->referenceTypeNode.subTypes;
34966
34967 UA_NODESTORE_RELEASE(server, refNode);
34968 return UA_STATUSCODE_GOOD;
34969}
34970
34971static UA_Boolean
34972matchClassMask(const UA_Node *node, UA_UInt32 nodeClassMask) {
34973 if(nodeClassMask != UA_NODECLASS_UNSPECIFIED &&
34974 (node->head.nodeClass & nodeClassMask) == 0)
34975 return false;
34976 return true;
34977}
34978
34979/****************/
34980/* IsNodeInTree */
34981/****************/
34982
34983/* Internal method to check if a node is already upwards from a leaf node */
34984
34985/* Keeps track of visited nodes to detect circular references */
34986struct ref_history {
34987 struct ref_history *parent; /* the previous element */
34988 const UA_NodePointer id; /* the id of the node at this depth */
34989 UA_UInt16 depth;
34990};
34991
34992static UA_Boolean
34993isNodeInTreeNoCircular(UA_Server *server,
34994 UA_NodePointer leafNode,
34995 UA_NodePointer nodeToFind,
34996 struct ref_history *visitedRefs,
34997 const UA_ReferenceTypeSet *relevantRefs) {
34998 if(UA_NodePointer_equal(p1: nodeToFind, p2: leafNode))
34999 return true;
35000
35001 if(visitedRefs->depth >= UA_MAX_TREE_RECURSE)
35002 return false;
35003
35004 const UA_Node *node = UA_NODESTORE_GETFROMREF(server, target: leafNode);
35005 if(!node)
35006 return false;
35007
35008 for(size_t i = 0; i < node->head.referencesSize; ++i) {
35009 UA_NodeReferenceKind *rk = &node->head.references[i];
35010 /* Search upwards in the tree */
35011 if(!rk->isInverse)
35012 continue;
35013
35014 /* Consider only the indicated reference types */
35015 if(!UA_ReferenceTypeSet_contains(set: relevantRefs, index: rk->referenceTypeIndex))
35016 continue;
35017
35018 /* Match the targets or recurse */
35019 const UA_ReferenceTarget *t = NULL;
35020 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
35021 /* Don't follow remote targets */
35022 if(!UA_NodePointer_isLocal(np: t->targetId))
35023 continue;
35024
35025 /* Check if we already have seen the referenced node and skip to
35026 * avoid endless recursion. Do this only at every 5th depth to save
35027 * effort. Circular dependencies are rare and forbidden for most
35028 * reference types. */
35029 if(visitedRefs->depth % 5 == 4) {
35030 struct ref_history *last = visitedRefs;
35031 UA_Boolean skip = false;
35032 while(last) {
35033 if(UA_NodePointer_equal(p1: last->id, p2: t->targetId)) {
35034 skip = true;
35035 break;
35036 }
35037 last = last->parent;
35038 }
35039 if(skip)
35040 continue;
35041 }
35042
35043 /* Stack-allocate the visitedRefs structure for the next depth */
35044 struct ref_history nextVisitedRefs = {visitedRefs, t->targetId,
35045 (UA_UInt16)(visitedRefs->depth+1)};
35046
35047 /* Recurse */
35048 UA_Boolean foundRecursive =
35049 isNodeInTreeNoCircular(server, leafNode: t->targetId, nodeToFind,
35050 visitedRefs: &nextVisitedRefs, relevantRefs);
35051 if(foundRecursive) {
35052 UA_NODESTORE_RELEASE(server, node);
35053 return true;
35054 }
35055 }
35056 }
35057
35058 UA_NODESTORE_RELEASE(server, node);
35059 return false;
35060}
35061
35062UA_Boolean
35063isNodeInTree(UA_Server *server, const UA_NodeId *leafNode,
35064 const UA_NodeId *nodeToFind,
35065 const UA_ReferenceTypeSet *relevantRefs) {
35066 UA_NodePointer leafP = UA_NodePointer_fromNodeId(id: leafNode);
35067 UA_NodePointer targetP = UA_NodePointer_fromNodeId(id: nodeToFind);
35068 struct ref_history visitedRefs = {NULL, leafP, 0};
35069 return isNodeInTreeNoCircular(server, leafNode: leafP, nodeToFind: targetP,
35070 visitedRefs: &visitedRefs, relevantRefs);
35071}
35072
35073UA_Boolean
35074isNodeInTree_singleRef(UA_Server *server, const UA_NodeId *leafNode,
35075 const UA_NodeId *nodeToFind, const UA_Byte relevantRefTypeIndex) {
35076 UA_ReferenceTypeSet reftypes = UA_REFTYPESET(index: relevantRefTypeIndex);
35077 return isNodeInTree(server, leafNode, nodeToFind, relevantRefs: &reftypes);
35078}
35079
35080static enum ZIP_CMP
35081cmpTarget(const void *a, const void *b) {
35082 const RefEntry *aa = (const RefEntry*)a;
35083 const RefEntry *bb = (const RefEntry*)b;
35084 if(aa->targetHash < bb->targetHash)
35085 return ZIP_CMP_LESS;
35086 if(aa->targetHash > bb->targetHash)
35087 return ZIP_CMP_MORE;
35088 return (enum ZIP_CMP)UA_ExpandedNodeId_order(n1: aa->target, n2: bb->target);
35089}
35090
35091ZIP_FUNCTIONS(RefHead, RefEntry, zipfields, RefEntry, zipfields, cmpTarget)
35092
35093UA_StatusCode
35094RefTree_init(RefTree *rt) {
35095 rt->size = 0;
35096 rt->capacity = 0;
35097 ZIP_INIT(&rt->head);
35098 size_t space = (sizeof(UA_ExpandedNodeId) + sizeof(RefEntry)) * UA_REFTREE_INITIAL_SIZE;
35099 rt->targets = (UA_ExpandedNodeId*)UA_malloc(size: space);
35100 if(!rt->targets)
35101 return UA_STATUSCODE_BADOUTOFMEMORY;
35102 rt->capacity = UA_REFTREE_INITIAL_SIZE;
35103 return UA_STATUSCODE_GOOD;
35104}
35105
35106void
35107RefTree_clear(RefTree *rt) {
35108 for(size_t i = 0; i < rt->size; i++)
35109 UA_ExpandedNodeId_clear(p: &rt->targets[i]);
35110 if(rt->targets)
35111 UA_free(ptr: rt->targets);
35112}
35113
35114/* Double the capacity of the reftree */
35115static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
35116RefTree_double(RefTree *rt) {
35117 size_t capacity = rt->capacity * 2;
35118 UA_assert(capacity > 0);
35119 size_t space = (sizeof(UA_ExpandedNodeId) + sizeof(RefEntry)) * capacity;
35120 UA_ExpandedNodeId *newTargets = (UA_ExpandedNodeId*)UA_realloc(ptr: rt->targets, size: space);
35121 if(!newTargets)
35122 return UA_STATUSCODE_BADOUTOFMEMORY;
35123
35124 /* Repair the pointers for the realloced array+tree */
35125 // What is this sorcery?
35126 // FIXME: This needs some cleaning up or explanation.
35127 // IMO uintptr could be completely avoided here.
35128 uintptr_t arraydiff = (uintptr_t)newTargets - (uintptr_t)rt->targets;
35129 RefEntry *reArray = (RefEntry*)
35130 ((uintptr_t)newTargets + (capacity * sizeof(UA_ExpandedNodeId)));
35131 uintptr_t entrydiff = (uintptr_t)reArray -
35132 ((uintptr_t)rt->targets + (rt->capacity * sizeof(UA_ExpandedNodeId)));
35133 RefEntry *oldReArray = (RefEntry*)
35134 ((uintptr_t)newTargets + (rt->capacity * sizeof(UA_ExpandedNodeId)));
35135 memmove(dest: reArray, src: oldReArray, n: rt->size * sizeof(RefEntry));
35136 for(size_t i = 0; i < rt->size; i++) {
35137 uintptr_t *left = (uintptr_t*)&ZIP_LEFT(&reArray[i], zipfields);
35138 uintptr_t *right = (uintptr_t*)&ZIP_RIGHT(&reArray[i], zipfields);
35139 if(*left != 0)
35140 *left += entrydiff;
35141 if(*right != 0)
35142 *right += entrydiff;
35143 reArray[i].target = (UA_ExpandedNodeId*)((uintptr_t)reArray[i].target + arraydiff);
35144 }
35145
35146 ZIP_ROOT(&rt->head) = (RefEntry*)((uintptr_t)ZIP_ROOT(&rt->head) + entrydiff);
35147 rt->capacity = capacity;
35148 rt->targets = newTargets;
35149 return UA_STATUSCODE_GOOD;
35150}
35151
35152static UA_StatusCode
35153RefTree_add(RefTree *rt, UA_NodePointer target, UA_Boolean *duplicate) {
35154 UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: target);
35155
35156 /* Is the target already in the tree? */
35157 RefEntry dummy;
35158 memset(s: &dummy, c: 0, n: sizeof(RefEntry));
35159 dummy.target = &en;
35160 dummy.targetHash = UA_ExpandedNodeId_hash(n: &en);
35161 if(ZIP_FIND(RefHead, &rt->head, &dummy)) {
35162 if(duplicate)
35163 *duplicate = true;
35164 return UA_STATUSCODE_GOOD;
35165 }
35166
35167 UA_StatusCode s = UA_STATUSCODE_GOOD;
35168 if(rt->capacity <= rt->size) {
35169 s = RefTree_double(rt);
35170 if(s != UA_STATUSCODE_GOOD)
35171 return s;
35172 }
35173 s = UA_ExpandedNodeId_copy(src: &en, dst: &rt->targets[rt->size]);
35174 if(s != UA_STATUSCODE_GOOD)
35175 return s;
35176 RefEntry *re = (RefEntry*)((uintptr_t)rt->targets +
35177 (sizeof(UA_ExpandedNodeId) * rt->capacity) +
35178 (sizeof(RefEntry) * rt->size));
35179 re->target = &rt->targets[rt->size];
35180 re->targetHash = dummy.targetHash;
35181 ZIP_INSERT(RefHead, &rt->head, re, UA_UInt32_random());
35182 rt->size++;
35183 return UA_STATUSCODE_GOOD;
35184}
35185
35186UA_StatusCode
35187RefTree_addNodeId(RefTree *rt, const UA_NodeId *target,
35188 UA_Boolean *duplicate) {
35189 return RefTree_add(rt, target: UA_NodePointer_fromNodeId(id: target), duplicate);
35190}
35191
35192UA_Boolean
35193RefTree_contains(RefTree *rt, const UA_ExpandedNodeId *target) {
35194 RefEntry dummy;
35195 dummy.target = target;
35196 dummy.targetHash = UA_ExpandedNodeId_hash(n: target);
35197 return !!ZIP_FIND(RefHead, &rt->head, &dummy);
35198}
35199
35200UA_Boolean
35201RefTree_containsNodeId(RefTree *rt, const UA_NodeId *target) {
35202 UA_ExpandedNodeId en;
35203 en.nodeId = *target;
35204 en.namespaceUri = UA_STRING_NULL;
35205 en.serverIndex = 0;
35206 return RefTree_contains(rt, target: &en);
35207}
35208
35209/********************/
35210/* Browse Recursive */
35211/********************/
35212
35213static UA_StatusCode
35214browseRecursiveInner(UA_Server *server, RefTree *rt, UA_UInt16 depth, UA_Boolean skip,
35215 UA_NodePointer nodeP, UA_BrowseDirection browseDirection,
35216 const UA_ReferenceTypeSet *refTypes, UA_UInt32 nodeClassMask) {
35217 /* Have we reached the max recursion depth? */
35218 if(depth >= UA_MAX_TREE_RECURSE)
35219 return UA_STATUSCODE_GOOD;
35220
35221 const UA_Node *node = UA_NODESTORE_GETFROMREF(server, target: nodeP);
35222 if(!node)
35223 return UA_STATUSCODE_BADNODEIDUNKNOWN;
35224
35225 UA_StatusCode retval = UA_STATUSCODE_GOOD;
35226 const UA_NodeHead *head = &node->head;
35227
35228 /* Add the current node to the results if we don't want to skip it (i.e. for
35229 * includeStartNodes) and it matches the nodeClassMask filter. Process the
35230 * children also if the nodeClassMask does not match. */
35231 if(!skip && matchClassMask(node, nodeClassMask)) {
35232 UA_Boolean duplicate = false;
35233 retval = RefTree_addNodeId(rt, target: &head->nodeId, duplicate: &duplicate);
35234 if(duplicate || retval != UA_STATUSCODE_GOOD)
35235 goto cleanup;
35236 }
35237
35238 for(size_t i = 0; i < head->referencesSize; i++) {
35239 UA_NodeReferenceKind *rk = &head->references[i];
35240
35241 /* Reference in the right direction? */
35242 if(rk->isInverse && browseDirection == UA_BROWSEDIRECTION_FORWARD)
35243 continue;
35244 if(!rk->isInverse && browseDirection == UA_BROWSEDIRECTION_INVERSE)
35245 continue;
35246
35247 /* Is the reference part of the hierarchy of references we look for? */
35248 if(!UA_ReferenceTypeSet_contains(set: refTypes, index: rk->referenceTypeIndex))
35249 continue;
35250
35251 const UA_ReferenceTarget *target = NULL;
35252 while((target = UA_NodeReferenceKind_iterate(rk, prev: target))) {
35253 if(UA_NodePointer_isLocal(np: target->targetId)) {
35254 retval = browseRecursiveInner(server, rt, depth: (UA_UInt16)(depth+1), false,
35255 nodeP: target->targetId, browseDirection,
35256 refTypes, nodeClassMask);
35257 } else {
35258 retval = RefTree_add(rt, target: target->targetId, NULL);
35259 }
35260 if(retval != UA_STATUSCODE_GOOD)
35261 goto cleanup;
35262 }
35263 }
35264
35265 cleanup:
35266 UA_NODESTORE_RELEASE(server, node);
35267 return retval;
35268}
35269
35270UA_StatusCode
35271browseRecursive(UA_Server *server, size_t startNodesSize, const UA_NodeId *startNodes,
35272 UA_BrowseDirection browseDirection, const UA_ReferenceTypeSet *refTypes,
35273 UA_UInt32 nodeClassMask, UA_Boolean includeStartNodes,
35274 size_t *resultsSize, UA_ExpandedNodeId **results) {
35275 RefTree rt;
35276 UA_StatusCode retval = RefTree_init(rt: &rt);
35277 if(retval != UA_STATUSCODE_GOOD)
35278 return retval;
35279
35280 for(size_t i = 0; i < startNodesSize; i++) {
35281 /* Call the inner recursive browse separately for the search direction.
35282 * Otherwise we might take one step up and another step down in the
35283 * search tree. */
35284 if(browseDirection == UA_BROWSEDIRECTION_FORWARD ||
35285 browseDirection == UA_BROWSEDIRECTION_BOTH)
35286 retval |= browseRecursiveInner(server, rt: &rt, depth: 0, skip: !includeStartNodes,
35287 nodeP: UA_NodePointer_fromNodeId(id: &startNodes[i]),
35288 browseDirection: UA_BROWSEDIRECTION_FORWARD,
35289 refTypes, nodeClassMask);
35290 if(browseDirection == UA_BROWSEDIRECTION_INVERSE ||
35291 browseDirection == UA_BROWSEDIRECTION_BOTH)
35292 retval |= browseRecursiveInner(server, rt: &rt, depth: 0, skip: !includeStartNodes,
35293 nodeP: UA_NodePointer_fromNodeId(id: &startNodes[i]),
35294 browseDirection: UA_BROWSEDIRECTION_INVERSE,
35295 refTypes, nodeClassMask);
35296 if(retval != UA_STATUSCODE_GOOD)
35297 break;
35298 }
35299
35300 if(rt.size > 0 && retval == UA_STATUSCODE_GOOD) {
35301 *results = rt.targets;
35302 *resultsSize = rt.size;
35303 } else {
35304 RefTree_clear(rt: &rt);
35305 }
35306 return retval;
35307}
35308
35309UA_StatusCode
35310UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd,
35311 size_t *resultsSize, UA_ExpandedNodeId **results) {
35312 UA_LOCK(&server->serviceMutex);
35313
35314 /* Set the list of relevant reference types */
35315 UA_ReferenceTypeSet refTypes;
35316 UA_StatusCode retval = referenceTypeIndices(server, refType: &bd->referenceTypeId,
35317 indices: &refTypes, includeSubtypes: bd->includeSubtypes);
35318 if(retval != UA_STATUSCODE_GOOD) {
35319 UA_UNLOCK(&server->serviceMutex);
35320 return retval;
35321 }
35322
35323 /* Browse */
35324 retval = browseRecursive(server, startNodesSize: 1, startNodes: &bd->nodeId, browseDirection: bd->browseDirection,
35325 refTypes: &refTypes, nodeClassMask: bd->nodeClassMask, false, resultsSize, results);
35326
35327 UA_UNLOCK(&server->serviceMutex);
35328 return retval;
35329}
35330
35331/**********/
35332/* Browse */
35333/**********/
35334
35335typedef struct {
35336 size_t size;
35337 size_t capacity;
35338 UA_ReferenceDescription *descr;
35339} RefResult;
35340
35341static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
35342RefResult_init(RefResult *rr) {
35343 memset(s: rr, c: 0, n: sizeof(RefResult));
35344 rr->descr = (UA_ReferenceDescription*)
35345 UA_Array_new(UA_REFTREE_INITIAL_SIZE, type: &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
35346 if(!rr->descr)
35347 return UA_STATUSCODE_BADOUTOFMEMORY;
35348 rr->capacity = UA_REFTREE_INITIAL_SIZE;
35349 rr->size = 0;
35350 return UA_STATUSCODE_GOOD;
35351}
35352
35353static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
35354RefResult_double(RefResult *rr) {
35355 size_t newSize = rr->capacity * 2;
35356 UA_ReferenceDescription *rd = (UA_ReferenceDescription*)
35357 UA_realloc(ptr: rr->descr, size: newSize * sizeof(UA_ReferenceDescription));
35358 if(!rd)
35359 return UA_STATUSCODE_BADOUTOFMEMORY;
35360 memset(s: &rd[rr->size], c: 0, n: sizeof(UA_ReferenceDescription) * (newSize - rr->size));
35361 rr->descr = rd;
35362 rr->capacity = newSize;
35363 return UA_STATUSCODE_GOOD;
35364}
35365
35366static void
35367RefResult_clear(RefResult *rr) {
35368 UA_assert(rr->descr != NULL);
35369 for(size_t i = 0; i < rr->size; i++)
35370 UA_ReferenceDescription_clear(p: &rr->descr[i]);
35371 UA_free(ptr: rr->descr);
35372}
35373
35374struct ContinuationPoint {
35375 ContinuationPoint *next;
35376 UA_ByteString identifier;
35377
35378 /* Parameters of the Browse Request */
35379 UA_BrowseDescription browseDescription;
35380 UA_UInt32 maxReferences;
35381 UA_ReferenceTypeSet relevantReferences;
35382
35383 /* The next target to be transmitted to the client */
35384 UA_ExpandedNodeId nextTarget;
35385 UA_Byte nextRefKindIndex;
35386};
35387
35388ContinuationPoint *
35389ContinuationPoint_clear(ContinuationPoint *cp) {
35390 UA_ByteString_clear(p: &cp->identifier);
35391 UA_BrowseDescription_clear(p: &cp->browseDescription);
35392 UA_ExpandedNodeId_clear(p: &cp->nextTarget);
35393 return cp->next;
35394}
35395
35396/* Target node on top of the stack */
35397static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
35398addReferenceDescription(UA_Server *server, RefResult *rr,
35399 const UA_NodeReferenceKind *ref, UA_UInt32 mask,
35400 UA_NodePointer nodeP, const UA_Node *curr) {
35401 /* Ensure capacity is left */
35402 UA_StatusCode retval = UA_STATUSCODE_GOOD;
35403 if(rr->size >= rr->capacity) {
35404 retval = RefResult_double(rr);
35405 if(retval != UA_STATUSCODE_GOOD)
35406 return retval;
35407 }
35408
35409 UA_ReferenceDescription *descr = &rr->descr[rr->size];
35410
35411 /* Fields without access to the actual node */
35412 UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: nodeP);
35413 retval = UA_ExpandedNodeId_copy(src: &en, dst: &descr->nodeId);
35414 if(mask & UA_BROWSERESULTMASK_REFERENCETYPEID) {
35415 const UA_NodeId *refTypeId =
35416 UA_NODESTORE_GETREFERENCETYPEID(server, ref->referenceTypeIndex);
35417 retval |= UA_NodeId_copy(src: refTypeId, dst: &descr->referenceTypeId);
35418 }
35419 if(mask & UA_BROWSERESULTMASK_ISFORWARD)
35420 descr->isForward = !ref->isInverse;
35421
35422 /* Remote references (ExpandedNodeId) are not further looked up here */
35423 if(!curr) {
35424 UA_ReferenceDescription_clear(p: descr);
35425 return retval;
35426 }
35427
35428 /* Fields that require the actual node */
35429 if(mask & UA_BROWSERESULTMASK_NODECLASS)
35430 descr->nodeClass = curr->head.nodeClass;
35431 if(mask & UA_BROWSERESULTMASK_BROWSENAME)
35432 retval |= UA_QualifiedName_copy(src: &curr->head.browseName, dst: &descr->browseName);
35433 if(mask & UA_BROWSERESULTMASK_DISPLAYNAME)
35434 retval |= UA_LocalizedText_copy(src: &curr->head.displayName, dst: &descr->displayName);
35435 if(mask & UA_BROWSERESULTMASK_TYPEDEFINITION) {
35436 if(curr->head.nodeClass == UA_NODECLASS_OBJECT ||
35437 curr->head.nodeClass == UA_NODECLASS_VARIABLE) {
35438 const UA_Node *type = getNodeType(server, head: &curr->head);
35439 if(type) {
35440 retval |= UA_NodeId_copy(src: &type->head.nodeId, dst: &descr->typeDefinition.nodeId);
35441 UA_NODESTORE_RELEASE(server, type);
35442 }
35443 }
35444 }
35445
35446 if(retval == UA_STATUSCODE_GOOD)
35447 rr->size++; /* Increase the counter */
35448 else
35449 UA_ReferenceDescription_clear(p: descr);
35450 return retval;
35451}
35452
35453/* Returns whether the node / continuationpoint is done */
35454static UA_StatusCode
35455browseReferences(UA_Server *server, const UA_NodeHead *head,
35456 ContinuationPoint *cp, RefResult *rr, UA_Boolean *done) {
35457 UA_assert(cp);
35458 const UA_BrowseDescription *bd = &cp->browseDescription;
35459
35460 size_t i = 0;
35461 const UA_ReferenceTarget *ref = NULL;
35462
35463 /* If the cp was previously used, skip forward to the next ReferenceType to
35464 * be transmitted. */
35465 if(cp->identifier.length > 0) {
35466 for(; i < head->referencesSize; ++i) {
35467 UA_NodeReferenceKind *rk = &head->references[i];
35468
35469 /* Was this the last transmitted ReferenceType? */
35470 if(head->references[i].referenceTypeIndex != cp->nextRefKindIndex)
35471 continue;
35472
35473 /* Reference in the right direction? */
35474 if(rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_FORWARD)
35475 continue;
35476 if(!rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_INVERSE)
35477 continue;
35478
35479 /* Get the next target */
35480 ref = UA_NodeReferenceKind_findTarget(rk, targetId: &cp->nextTarget);
35481 if(ref)
35482 break;
35483
35484 /* The target no longer exists for this ReferenceType (and
35485 * direction). Continue to iterate for the case that a nodestore has
35486 * a duplicate UA_NodeReferenceKind (should not happen though). */
35487 }
35488
35489 /* Fail with an error if the reference no longer exists. */
35490 if(!ref)
35491 return UA_STATUSCODE_BADINTERNALERROR;
35492 }
35493
35494 /* Loop over the ReferenceTypes */
35495 UA_StatusCode retval = UA_STATUSCODE_GOOD;
35496 for(; i < head->referencesSize; ++i) {
35497 UA_NodeReferenceKind *rk = &head->references[i];
35498
35499 /* Reference in the right direction? */
35500 if(rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_FORWARD)
35501 continue;
35502 if(!rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_INVERSE)
35503 continue;
35504
35505 /* Is the reference part of the hierarchy of references we look for? */
35506 if(!UA_ReferenceTypeSet_contains(set: &cp->relevantReferences,
35507 index: rk->referenceTypeIndex))
35508 continue;
35509
35510 /* We have a matching ReferenceType! */
35511
35512 /* Loop over the targets for the ReferenceType. Start with the first
35513 * entry if we don't have a known entry-point from the cp. */
35514 if(!ref)
35515 ref = UA_NodeReferenceKind_iterate(rk, prev: ref);
35516 for(;ref; ref = UA_NodeReferenceKind_iterate(rk, prev: ref)) {
35517 /* Get the node if it is not a remote reference */
35518 const UA_Node *target =
35519 UA_NODESTORE_GETFROMREF(server, target: ref->targetId);
35520
35521 /* Test if the node class matches */
35522 if(target && !matchClassMask(node: target, nodeClassMask: bd->nodeClassMask)) {
35523 UA_NODESTORE_RELEASE(server, target);
35524 continue;
35525 }
35526
35527 /* We have a matching target! */
35528
35529 /* Reached maxrefs. Update the cp and bail. */
35530 if(rr->size >= cp->maxReferences) {
35531 if(target)
35532 UA_NODESTORE_RELEASE(server, target);
35533 cp->nextRefKindIndex = rk->referenceTypeIndex;
35534 /* Make a deep copy */
35535 UA_ExpandedNodeId tmpEn =
35536 UA_NodePointer_toExpandedNodeId(np: ref->targetId);
35537 UA_ExpandedNodeId_clear(p: &cp->nextTarget);
35538 return UA_ExpandedNodeId_copy(src: &tmpEn, dst: &cp->nextTarget);
35539 }
35540
35541 /* Copy the node description. Target is on top of the stack */
35542 retval = addReferenceDescription(server, rr, ref: rk, mask: bd->resultMask,
35543 nodeP: ref->targetId, curr: target);
35544 if(target)
35545 UA_NODESTORE_RELEASE(server, target);
35546 if(retval != UA_STATUSCODE_GOOD)
35547 return retval;
35548 }
35549 }
35550
35551 /* The node is done */
35552 *done = true;
35553 return UA_STATUSCODE_GOOD;
35554}
35555
35556/* Results for a single browsedescription. This is the inner loop for both
35557 * Browse and BrowseNext. The ContinuationPoint contains all the data used.
35558 * Including the BrowseDescription. Returns whether there are remaining
35559 * references. */
35560static UA_Boolean
35561browseWithContinuation(UA_Server *server, UA_Session *session,
35562 ContinuationPoint *cp, UA_BrowseResult *result) {
35563 UA_assert(cp);
35564 const UA_BrowseDescription *descr = &cp->browseDescription;
35565
35566 /* Is the browsedirection valid? */
35567 if(descr->browseDirection != UA_BROWSEDIRECTION_BOTH &&
35568 descr->browseDirection != UA_BROWSEDIRECTION_FORWARD &&
35569 descr->browseDirection != UA_BROWSEDIRECTION_INVERSE) {
35570 result->statusCode = UA_STATUSCODE_BADBROWSEDIRECTIONINVALID;
35571 return true;
35572 }
35573
35574 /* Is the reference type valid? */
35575 if(!UA_NodeId_isNull(p: &descr->referenceTypeId)) {
35576 const UA_Node *reftype = UA_NODESTORE_GET(server, &descr->referenceTypeId);
35577 if(!reftype) {
35578 result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
35579 return true;
35580 }
35581
35582 UA_Boolean isRef = (reftype->head.nodeClass == UA_NODECLASS_REFERENCETYPE);
35583 UA_NODESTORE_RELEASE(server, reftype);
35584
35585 if(!isRef) {
35586 result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
35587 return true;
35588 }
35589 }
35590
35591 const UA_Node *node = UA_NODESTORE_GET(server, &descr->nodeId);
35592 if(!node) {
35593 result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
35594 return true;
35595 }
35596
35597 if(session != &server->adminSession &&
35598 !server->config.accessControl.
35599 allowBrowseNode(server, &server->config.accessControl,
35600 &session->sessionId, session->sessionHandle,
35601 &descr->nodeId, node->head.context)) {
35602 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
35603 UA_NODESTORE_RELEASE(server, node);
35604 return true;
35605 }
35606
35607 RefResult rr;
35608 result->statusCode = RefResult_init(rr: &rr);
35609 if(result->statusCode != UA_STATUSCODE_GOOD) {
35610 UA_NODESTORE_RELEASE(server, node);
35611 return true;
35612 }
35613
35614 /* Browse the references */
35615 UA_Boolean done = false;
35616 result->statusCode = browseReferences(server, head: &node->head, cp, rr: &rr, done: &done);
35617 UA_NODESTORE_RELEASE(server, node);
35618 if(result->statusCode != UA_STATUSCODE_GOOD) {
35619 RefResult_clear(rr: &rr);
35620 return true;
35621 }
35622
35623 /* Move results */
35624 if(rr.size > 0) {
35625 result->references = rr.descr;
35626 result->referencesSize = rr.size;
35627 } else {
35628 /* No relevant references, return array of length zero */
35629 RefResult_clear(rr: &rr);
35630 result->references = (UA_ReferenceDescription*)UA_EMPTY_ARRAY_SENTINEL;
35631 }
35632
35633 return done;
35634}
35635
35636/* Start to browse with no previous cp */
35637void
35638Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxrefs,
35639 const UA_BrowseDescription *descr, UA_BrowseResult *result) {
35640 /* Stack-allocate a temporary cp */
35641 ContinuationPoint cp;
35642 memset(s: &cp, c: 0, n: sizeof(ContinuationPoint));
35643 cp.maxReferences = *maxrefs;
35644 cp.browseDescription = *descr; /* Shallow copy. Deep-copy later if we persist the cp. */
35645
35646 /* How many references can we return at most? */
35647 if(cp.maxReferences == 0) {
35648 if(server->config.maxReferencesPerNode != 0) {
35649 cp.maxReferences = server->config.maxReferencesPerNode;
35650 } else {
35651 cp.maxReferences = UA_INT32_MAX;
35652 }
35653 } else {
35654 if(server->config.maxReferencesPerNode != 0 &&
35655 cp.maxReferences > server->config.maxReferencesPerNode) {
35656 cp.maxReferences= server->config.maxReferencesPerNode;
35657 }
35658 }
35659
35660 /* Get the list of relevant reference types */
35661 result->statusCode =
35662 referenceTypeIndices(server, refType: &descr->referenceTypeId,
35663 indices: &cp.relevantReferences, includeSubtypes: descr->includeSubtypes);
35664 if(result->statusCode != UA_STATUSCODE_GOOD)
35665 return;
35666
35667 UA_Boolean done = browseWithContinuation(server, session, cp: &cp, result);
35668
35669 /* Exit early if done or an error occurred */
35670 if(done || result->statusCode != UA_STATUSCODE_GOOD)
35671 return;
35672
35673 /* Persist the new continuation point */
35674
35675 ContinuationPoint *cp2 = NULL;
35676 UA_Guid *ident = NULL;
35677 UA_StatusCode retval = UA_STATUSCODE_GOOD;
35678
35679 /* Enough space for the continuation point? */
35680 if(session->availableContinuationPoints == 0) {
35681 retval = UA_STATUSCODE_BADNOCONTINUATIONPOINTS;
35682 goto cleanup;
35683 }
35684
35685 /* Allocate and fill the data structure */
35686 cp2 = (ContinuationPoint*)UA_malloc(size: sizeof(ContinuationPoint));
35687 if(!cp2) {
35688 retval = UA_STATUSCODE_BADOUTOFMEMORY;
35689 goto cleanup;
35690 }
35691
35692 memset(s: cp2, c: 0, n: sizeof(ContinuationPoint));
35693 /* The BrowseDescription is only a shallow copy in cp */
35694 retval = UA_BrowseDescription_copy(src: descr, dst: &cp2->browseDescription);
35695 if(retval != UA_STATUSCODE_GOOD)
35696 goto cleanup;
35697 cp2->maxReferences = cp.maxReferences;
35698 cp2->relevantReferences = cp.relevantReferences;
35699 cp2->nextTarget = cp.nextTarget;
35700 cp2->nextRefKindIndex = cp.nextRefKindIndex;
35701
35702 /* Create a random bytestring via a Guid */
35703 ident = UA_Guid_new();
35704 if(!ident) {
35705 retval = UA_STATUSCODE_BADOUTOFMEMORY;
35706 goto cleanup;
35707 }
35708 *ident = UA_Guid_random();
35709 cp2->identifier.data = (UA_Byte*)ident;
35710 cp2->identifier.length = sizeof(UA_Guid);
35711
35712 /* Return the cp identifier */
35713 retval = UA_ByteString_copy(src: &cp2->identifier, dst: &result->continuationPoint);
35714 if(retval != UA_STATUSCODE_GOOD)
35715 goto cleanup;
35716
35717 /* Attach the cp to the session */
35718 cp2->next = session->continuationPoints;
35719 session->continuationPoints = cp2;
35720 --session->availableContinuationPoints;
35721 return;
35722
35723 cleanup:
35724 if(cp2) {
35725 ContinuationPoint_clear(cp: cp2);
35726 UA_free(ptr: cp2);
35727 }
35728 UA_BrowseResult_clear(p: result);
35729 result->statusCode = retval;
35730}
35731
35732void Service_Browse(UA_Server *server, UA_Session *session,
35733 const UA_BrowseRequest *request, UA_BrowseResponse *response) {
35734 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing BrowseRequest");
35735 UA_LOCK_ASSERT(&server->serviceMutex, 1);
35736
35737 /* Test the number of operations in the request */
35738 if(server->config.maxNodesPerBrowse != 0 &&
35739 request->nodesToBrowseSize > server->config.maxNodesPerBrowse) {
35740 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
35741 return;
35742 }
35743
35744 /* No views supported at the moment */
35745 if(!UA_NodeId_isNull(p: &request->view.viewId)) {
35746 response->responseHeader.serviceResult = UA_STATUSCODE_BADVIEWIDUNKNOWN;
35747 return;
35748 }
35749
35750 response->responseHeader.serviceResult =
35751 UA_Server_processServiceOperations(server, session,
35752 operationCallback: (UA_ServiceOperation)Operation_Browse,
35753 context: &request->requestedMaxReferencesPerNode,
35754 requestOperations: &request->nodesToBrowseSize,
35755 requestOperationsType: &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION],
35756 responseOperations: &response->resultsSize,
35757 responseOperationsType: &UA_TYPES[UA_TYPES_BROWSERESULT]);
35758}
35759
35760UA_BrowseResult
35761UA_Server_browse(UA_Server *server, UA_UInt32 maxReferences,
35762 const UA_BrowseDescription *bd) {
35763 UA_BrowseResult result;
35764 UA_BrowseResult_init(p: &result);
35765 UA_LOCK(&server->serviceMutex);
35766 Operation_Browse(server, session: &server->adminSession, maxrefs: &maxReferences, descr: bd, result: &result);
35767 UA_UNLOCK(&server->serviceMutex);
35768 return result;
35769}
35770
35771static void
35772Operation_BrowseNext(UA_Server *server, UA_Session *session,
35773 const UA_Boolean *releaseContinuationPoints,
35774 const UA_ByteString *continuationPoint, UA_BrowseResult *result) {
35775 /* Find the continuation point */
35776 ContinuationPoint **prev = &session->continuationPoints;
35777 ContinuationPoint *cp;
35778 while((cp = *prev)) {
35779 if(UA_ByteString_equal(string1: &cp->identifier, string2: continuationPoint))
35780 break;
35781 prev = &cp->next;
35782 }
35783 if(!cp) {
35784 result->statusCode = UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
35785 return;
35786 }
35787
35788 /* Remove the cp */
35789 if(*releaseContinuationPoints) {
35790 *prev = ContinuationPoint_clear(cp);
35791 UA_free(ptr: cp);
35792 ++session->availableContinuationPoints;
35793 return;
35794 }
35795
35796 /* Continue browsing */
35797 UA_Boolean done = browseWithContinuation(server, session, cp, result);
35798
35799 if(done) {
35800 /* Remove the cp if there are no references left */
35801 *prev = ContinuationPoint_clear(cp);
35802 UA_free(ptr: cp);
35803 ++session->availableContinuationPoints;
35804 } else {
35805 /* Return the cp identifier */
35806 UA_StatusCode retval =
35807 UA_ByteString_copy(src: &cp->identifier, dst: &result->continuationPoint);
35808 if(retval != UA_STATUSCODE_GOOD) {
35809 UA_BrowseResult_clear(p: result);
35810 result->statusCode = retval;
35811 }
35812 }
35813}
35814
35815void
35816Service_BrowseNext(UA_Server *server, UA_Session *session,
35817 const UA_BrowseNextRequest *request,
35818 UA_BrowseNextResponse *response) {
35819 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
35820 "Processing BrowseNextRequest");
35821 UA_LOCK_ASSERT(&server->serviceMutex, 1);
35822
35823 UA_Boolean releaseContinuationPoints =
35824 request->releaseContinuationPoints; /* request is const */
35825 response->responseHeader.serviceResult =
35826 UA_Server_processServiceOperations(server, session,
35827 operationCallback: (UA_ServiceOperation)Operation_BrowseNext,
35828 context: &releaseContinuationPoints,
35829 requestOperations: &request->continuationPointsSize,
35830 requestOperationsType: &UA_TYPES[UA_TYPES_BYTESTRING],
35831 responseOperations: &response->resultsSize,
35832 responseOperationsType: &UA_TYPES[UA_TYPES_BROWSERESULT]);
35833}
35834
35835UA_BrowseResult
35836UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
35837 const UA_ByteString *continuationPoint) {
35838 UA_BrowseResult result;
35839 UA_BrowseResult_init(p: &result);
35840 UA_LOCK(&server->serviceMutex);
35841 Operation_BrowseNext(server, session: &server->adminSession, releaseContinuationPoints: &releaseContinuationPoint,
35842 continuationPoint, result: &result);
35843 UA_UNLOCK(&server->serviceMutex);
35844 return result;
35845}
35846
35847/***********************/
35848/* TranslateBrowsePath */
35849/***********************/
35850
35851/* Find all entries for that hash. There are duplicate for the possible hash
35852 * collisions. The exact browsename is checked afterwards. */
35853static UA_StatusCode
35854recursiveAddBrowseHashTarget(RefTree *results, struct aa_head *head,
35855 const UA_ReferenceTarget *rt) {
35856 UA_assert(rt);
35857 UA_StatusCode res = RefTree_add(rt: results, target: rt->targetId, NULL);
35858 UA_ReferenceTarget *prev = (UA_ReferenceTarget*)aa_prev(head, elem: rt);
35859 while(prev && prev->targetNameHash == rt->targetNameHash) {
35860 res |= RefTree_add(rt: results, target: prev->targetId, NULL);
35861 prev = (UA_ReferenceTarget*)aa_prev(head, elem: prev);
35862 }
35863 UA_ReferenceTarget *next= (UA_ReferenceTarget*)aa_next(head, elem: rt);
35864 while(next && next->targetNameHash == rt->targetNameHash) {
35865 res |= RefTree_add(rt: results, target: next->targetId, NULL);
35866 next = (UA_ReferenceTarget*)aa_next(head, elem: next);
35867 }
35868 return res;
35869}
35870
35871static UA_StatusCode
35872walkBrowsePathElement(UA_Server *server, UA_Session *session,
35873 const UA_RelativePath *path, const size_t pathIndex,
35874 UA_UInt32 nodeClassMask, const UA_QualifiedName *lastBrowseName,
35875 UA_BrowsePathResult *result, RefTree *current, RefTree *next) {
35876 /* For the next level. Note the difference from lastBrowseName */
35877 const UA_RelativePathElement *elem = &path->elements[pathIndex];
35878 UA_UInt32 browseNameHash = UA_QualifiedName_hash(q: &elem->targetName);
35879
35880 /* Get the relevant ReferenceTypes */
35881 UA_ReferenceTypeSet refTypes;
35882 UA_StatusCode res =
35883 referenceTypeIndices(server, refType: &elem->referenceTypeId,
35884 indices: &refTypes, includeSubtypes: elem->includeSubtypes);
35885 if(res != UA_STATUSCODE_GOOD)
35886 return UA_STATUSCODE_BADNOMATCH;
35887
35888 struct aa_head _refNameTree = refNameTree;
35889
35890 /* Loop over all Nodes in the current depth level */
35891 for(size_t i = 0; i < current->size; i++) {
35892 /* Remote Node. Immediately add to the results with the
35893 * RemainingPathIndex set. */
35894 if(!UA_ExpandedNodeId_isLocal(n: &current->targets[i])) {
35895 /* Increase the size of the results array */
35896 UA_BrowsePathTarget *tmpResults = (UA_BrowsePathTarget*)
35897 UA_realloc(ptr: result->targets, size: sizeof(UA_BrowsePathTarget) *
35898 (result->targetsSize + 1));
35899 if(!tmpResults)
35900 return UA_STATUSCODE_BADOUTOFMEMORY;
35901 result->targets = tmpResults;
35902
35903 /* Copy over the result */
35904 res = UA_ExpandedNodeId_copy(src: &current->targets[i],
35905 dst: &result->targets[result->targetsSize].targetId);
35906 result->targets[result->targetsSize].remainingPathIndex = (UA_UInt32)pathIndex;
35907 result->targetsSize++;
35908 if(res != UA_STATUSCODE_GOOD)
35909 break;
35910 continue;
35911 }
35912
35913 /* Local Node. Add to the tree of results at the next depth. */
35914 const UA_Node *node = UA_NODESTORE_GET(server, &current->targets[i].nodeId);
35915 if(!node)
35916 continue;
35917
35918 /* Test whether the node fits the class mask */
35919 UA_Boolean skip = !matchClassMask(node, nodeClassMask);
35920
35921 /* Does the BrowseName match for the current node (not the references
35922 * going out here) */
35923 skip |= (lastBrowseName &&
35924 !UA_QualifiedName_equal(qn1: lastBrowseName, qn2: &node->head.browseName));
35925
35926 if(skip) {
35927 UA_NODESTORE_RELEASE(server, node);
35928 continue;
35929 }
35930
35931 /* Loop over the ReferenceKinds */
35932 for(size_t j = 0; j < node->head.referencesSize; j++) {
35933 UA_NodeReferenceKind *rk = &node->head.references[j];
35934
35935 /* Does the direction of the reference match? */
35936 if(rk->isInverse != elem->isInverse)
35937 continue;
35938
35939 /* Does the reference type match? */
35940 if(!UA_ReferenceTypeSet_contains(set: &refTypes, index: rk->referenceTypeIndex))
35941 continue;
35942
35943 if(rk->hasRefTree) {
35944 /* Retrieve by BrowseName hash. We might have several nodes where
35945 * the hash matches. The exact BrowseName will be verified in the
35946 * next iteration of the outer loop. So we only have to retrieve
35947 * every node just once. */
35948 _refNameTree.root = rk->targets.tree.nameTreeRoot;
35949 UA_ReferenceTarget *rt = (UA_ReferenceTarget*)
35950 aa_find(head: &_refNameTree, key: &browseNameHash);
35951 if(!rt)
35952 continue;
35953
35954 res = recursiveAddBrowseHashTarget(results: next, head: &_refNameTree, rt);
35955 if(res != UA_STATUSCODE_GOOD)
35956 break;
35957 } else {
35958 /* The array entries don't have a BrowseName hash. Add all of
35959 * them at this level to be checked with a full string
35960 * comparison. */
35961 for(size_t k = 0; k < rk->targetsSize; k++) {
35962 if(rk->targets.array[k].targetNameHash != browseNameHash)
35963 continue;
35964 res = RefTree_add(rt: next, target: rk->targets.array[k].targetId, NULL);
35965 if(res != UA_STATUSCODE_GOOD)
35966 break;
35967 }
35968 if(res != UA_STATUSCODE_GOOD)
35969 break;
35970 }
35971 }
35972
35973 UA_NODESTORE_RELEASE(server, node);
35974 }
35975 return res;
35976}
35977
35978static void
35979Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session,
35980 const UA_UInt32 *nodeClassMask,
35981 const UA_BrowsePath *path,
35982 UA_BrowsePathResult *result) {
35983 UA_LOCK_ASSERT(&server->serviceMutex, 1);
35984
35985 if(path->relativePath.elementsSize == 0) {
35986 result->statusCode = UA_STATUSCODE_BADNOTHINGTODO;
35987 return;
35988 }
35989
35990 /* RelativePath elements must not have an empty targetName */
35991 for(size_t i = 0; i < path->relativePath.elementsSize; ++i) {
35992 if(UA_QualifiedName_isNull(q: &path->relativePath.elements[i].targetName)) {
35993 result->statusCode = UA_STATUSCODE_BADBROWSENAMEINVALID;
35994 return;
35995 }
35996 }
35997
35998 /* Check if the starting node exists */
35999 const UA_Node *startingNode = UA_NODESTORE_GET(server, &path->startingNode);
36000 if(!startingNode) {
36001 result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36002 return;
36003 }
36004 UA_NODESTORE_RELEASE(server, startingNode);
36005
36006 /* Create two RefTrees that are alternated between path elements */
36007 RefTree rt1;
36008 RefTree rt2;
36009 RefTree *current = &rt1;
36010 RefTree *next = &rt2;
36011 RefTree *tmp;
36012 result->statusCode |= RefTree_init(rt: &rt1);
36013 result->statusCode |= RefTree_init(rt: &rt2);
36014 UA_BrowsePathTarget *tmpResults = NULL;
36015 UA_QualifiedName *browseNameFilter = NULL;
36016 if(result->statusCode != UA_STATUSCODE_GOOD)
36017 goto cleanup;
36018
36019 /* Copy the starting node into next */
36020 result->statusCode = RefTree_addNodeId(rt: next, target: &path->startingNode, NULL);
36021 if(result->statusCode != UA_STATUSCODE_GOOD)
36022 goto cleanup;
36023
36024 /* Walk the path elements. Retrieve the nodes only once from the NodeStore.
36025 * Hence the BrowseName is checked with one element "delay". */
36026 for(size_t i = 0; i < path->relativePath.elementsSize; i++) {
36027 /* Switch the trees */
36028 tmp = current;
36029 current = next;
36030 next = tmp;
36031
36032 /* Clear up current, keep the capacity */
36033 for(size_t j = 0; j < next->size; j++)
36034 UA_ExpandedNodeId_clear(p: &next->targets[j]);
36035 next->size = 0;
36036 ZIP_INIT(&next->head);
36037
36038 /* Do this check after next->size has been set to zero */
36039 if(current->size == 0)
36040 break;
36041
36042 /* Walk element for all NodeIds in the "current" tree.
36043 * Puts new results in the "next" tree. */
36044 result->statusCode =
36045 walkBrowsePathElement(server, session, path: &path->relativePath, pathIndex: i,
36046 nodeClassMask: *nodeClassMask, lastBrowseName: browseNameFilter, result, current, next);
36047 if(result->statusCode != UA_STATUSCODE_GOOD)
36048 goto cleanup;
36049
36050 browseNameFilter = &path->relativePath.elements[i].targetName;
36051 }
36052
36053 /* Allocate space for the results array */
36054 tmpResults = (UA_BrowsePathTarget*)
36055 UA_realloc(ptr: result->targets, size: sizeof(UA_BrowsePathTarget) *
36056 (result->targetsSize + next->size));
36057 if(!tmpResults && next->size > 0) {
36058 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
36059 goto cleanup;
36060 }
36061 result->targets = tmpResults;
36062
36063 for(size_t k = 0; k < next->size; k++) {
36064 /* Check the BrowseName. It has been filtered only via its hash so far. */
36065 const UA_Node *node = UA_NODESTORE_GET(server, &next->targets[k].nodeId);
36066 if(!node)
36067 continue;
36068 UA_Boolean match = UA_QualifiedName_equal(qn1: browseNameFilter, qn2: &node->head.browseName);
36069 UA_NODESTORE_RELEASE(server, node);
36070 if(!match)
36071 continue;
36072
36073 /* Move to the target to the results array */
36074 result->targets[result->targetsSize].targetId = next->targets[k];
36075 result->targets[result->targetsSize].remainingPathIndex = UA_UINT32_MAX;
36076 UA_ExpandedNodeId_init(p: &next->targets[k]);
36077 result->targetsSize++;
36078 }
36079
36080 /* No results => BadNoMatch status code */
36081 if(result->targetsSize == 0 && result->statusCode == UA_STATUSCODE_GOOD)
36082 result->statusCode = UA_STATUSCODE_BADNOMATCH;
36083
36084 /* Clean up the temporary arrays and the targets */
36085 cleanup:
36086 RefTree_clear(rt: &rt1);
36087 RefTree_clear(rt: &rt2);
36088 if(result->statusCode != UA_STATUSCODE_GOOD) {
36089 for(size_t i = 0; i < result->targetsSize; ++i)
36090 UA_BrowsePathTarget_clear(p: &result->targets[i]);
36091 if(result->targets)
36092 UA_free(ptr: result->targets);
36093 result->targets = NULL;
36094 result->targetsSize = 0;
36095 }
36096}
36097
36098UA_BrowsePathResult
36099translateBrowsePathToNodeIds(UA_Server *server,
36100 const UA_BrowsePath *browsePath) {
36101 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36102 UA_BrowsePathResult result;
36103 UA_BrowsePathResult_init(p: &result);
36104 UA_UInt32 nodeClassMask = 0; /* All node classes */
36105 Operation_TranslateBrowsePathToNodeIds(server, session: &server->adminSession, nodeClassMask: &nodeClassMask,
36106 path: browsePath, result: &result);
36107 return result;
36108}
36109
36110UA_BrowsePathResult
36111UA_Server_translateBrowsePathToNodeIds(UA_Server *server,
36112 const UA_BrowsePath *browsePath) {
36113 UA_LOCK(&server->serviceMutex);
36114 UA_BrowsePathResult result = translateBrowsePathToNodeIds(server, browsePath);
36115 UA_UNLOCK(&server->serviceMutex);
36116 return result;
36117}
36118
36119void
36120Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
36121 const UA_TranslateBrowsePathsToNodeIdsRequest *request,
36122 UA_TranslateBrowsePathsToNodeIdsResponse *response) {
36123 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
36124 "Processing TranslateBrowsePathsToNodeIdsRequest");
36125 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36126
36127 /* Test the number of operations in the request */
36128 if(server->config.maxNodesPerTranslateBrowsePathsToNodeIds != 0 &&
36129 request->browsePathsSize > server->config.maxNodesPerTranslateBrowsePathsToNodeIds) {
36130 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36131 return;
36132 }
36133
36134 UA_UInt32 nodeClassMask = 0; /* All node classes */
36135 response->responseHeader.serviceResult =
36136 UA_Server_processServiceOperations(server, session,
36137 operationCallback: (UA_ServiceOperation)Operation_TranslateBrowsePathToNodeIds,
36138 context: &nodeClassMask,
36139 requestOperations: &request->browsePathsSize, requestOperationsType: &UA_TYPES[UA_TYPES_BROWSEPATH],
36140 responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
36141}
36142
36143UA_BrowsePathResult
36144browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
36145 size_t browsePathSize, const UA_QualifiedName *browsePath) {
36146 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36147
36148 UA_BrowsePathResult bpr;
36149 UA_BrowsePathResult_init(p: &bpr);
36150 if(browsePathSize > UA_MAX_TREE_RECURSE) {
36151 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
36152 msg: "Simplified Browse Path too long");
36153 bpr.statusCode = UA_STATUSCODE_BADINTERNALERROR;
36154 return bpr;
36155 }
36156
36157 /* Construct the BrowsePath */
36158 UA_BrowsePath bp;
36159 UA_BrowsePath_init(p: &bp);
36160 bp.startingNode = origin;
36161
36162 UA_RelativePathElement rpe[UA_MAX_TREE_RECURSE];
36163 memset(s: rpe, c: 0, n: sizeof(UA_RelativePathElement) * browsePathSize);
36164 for(size_t j = 0; j < browsePathSize; j++) {
36165 rpe[j].referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
36166 rpe[j].includeSubtypes = true;
36167 rpe[j].targetName = browsePath[j];
36168 }
36169 bp.relativePath.elements = rpe;
36170 bp.relativePath.elementsSize = browsePathSize;
36171
36172 /* Browse */
36173 UA_UInt32 nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_OBJECTTYPE;
36174
36175 Operation_TranslateBrowsePathToNodeIds(server, session: &server->adminSession, nodeClassMask: &nodeClassMask, path: &bp, result: &bpr);
36176 return bpr;
36177}
36178
36179UA_BrowsePathResult
36180UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
36181 size_t browsePathSize, const UA_QualifiedName *browsePath) {
36182 UA_LOCK(&server->serviceMutex);
36183 UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin, browsePathSize, browsePath);
36184 UA_UNLOCK(&server->serviceMutex);
36185 return bpr;
36186}
36187
36188/************/
36189/* Register */
36190/************/
36191
36192void Service_RegisterNodes(UA_Server *server, UA_Session *session,
36193 const UA_RegisterNodesRequest *request,
36194 UA_RegisterNodesResponse *response) {
36195 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
36196 "Processing RegisterNodesRequest");
36197 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36198
36199 //TODO: hang the nodeids to the session if really needed
36200 if(request->nodesToRegisterSize == 0) {
36201 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
36202 return;
36203 }
36204
36205 /* Test the number of operations in the request */
36206 if(server->config.maxNodesPerRegisterNodes != 0 &&
36207 request->nodesToRegisterSize > server->config.maxNodesPerRegisterNodes) {
36208 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36209 return;
36210 }
36211
36212 response->responseHeader.serviceResult =
36213 UA_Array_copy(src: request->nodesToRegister, size: request->nodesToRegisterSize,
36214 dst: (void**)&response->registeredNodeIds, type: &UA_TYPES[UA_TYPES_NODEID]);
36215 if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD)
36216 response->registeredNodeIdsSize = request->nodesToRegisterSize;
36217}
36218
36219void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
36220 const UA_UnregisterNodesRequest *request,
36221 UA_UnregisterNodesResponse *response) {
36222 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
36223 "Processing UnRegisterNodesRequest");
36224 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36225
36226 //TODO: remove the nodeids from the session if really needed
36227 if(request->nodesToUnregisterSize == 0)
36228 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
36229
36230 /* Test the number of operations in the request */
36231 if(server->config.maxNodesPerRegisterNodes != 0 &&
36232 request->nodesToUnregisterSize > server->config.maxNodesPerRegisterNodes) {
36233 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36234 return;
36235 }
36236}
36237
36238/**** amalgamated original file "/src/server/ua_services_method.c" ****/
36239
36240/* This Source Code Form is subject to the terms of the Mozilla Public
36241 * License, v. 2.0. If a copy of the MPL was not distributed with this
36242 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
36243 *
36244 * Copyright 2015 (c) Chris Iatrou
36245 * Copyright 2015-2017 (c) Florian Palm
36246 * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
36247 * Copyright 2015-2016 (c) Sten Grüner
36248 * Copyright 2015 (c) Oleksiy Vasylyev
36249 * Copyright 2016 (c) LEvertz
36250 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
36251 * Copyright 2017 (c) Julian Grothoff
36252 * Copyright 2020 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
36253 */
36254
36255
36256#ifdef UA_ENABLE_METHODCALLS /* conditional compilation */
36257
36258static const UA_VariableNode *
36259getArgumentsVariableNode(UA_Server *server, const UA_NodeHead *head,
36260 UA_String withBrowseName) {
36261 for(size_t i = 0; i < head->referencesSize; ++i) {
36262 const UA_NodeReferenceKind *rk = &head->references[i];
36263 if(rk->isInverse != false)
36264 continue;
36265 if(rk->referenceTypeIndex != UA_REFERENCETYPEINDEX_HASPROPERTY)
36266 continue;
36267 const UA_ReferenceTarget *t = NULL;
36268 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
36269 const UA_Node *refTarget =
36270 UA_NODESTORE_GETFROMREF(server, target: t->targetId);
36271 if(!refTarget)
36272 continue;
36273 if(refTarget->head.nodeClass == UA_NODECLASS_VARIABLE &&
36274 refTarget->head.browseName.namespaceIndex == 0 &&
36275 UA_String_equal(s1: &withBrowseName, s2: &refTarget->head.browseName.name)) {
36276 return &refTarget->variableNode;
36277 }
36278 UA_NODESTORE_RELEASE(server, refTarget);
36279 }
36280 }
36281 return NULL;
36282}
36283
36284/* inputArgumentResults has the length request->inputArgumentsSize */
36285static UA_StatusCode
36286typeCheckArguments(UA_Server *server, UA_Session *session,
36287 const UA_VariableNode *argRequirements, size_t argsSize,
36288 UA_Variant *args, UA_StatusCode *inputArgumentResults) {
36289 /* Verify that we have a Variant containing UA_Argument (scalar or array) in
36290 * the "InputArguments" node */
36291 if(argRequirements->valueSource != UA_VALUESOURCE_DATA)
36292 return UA_STATUSCODE_BADINTERNALERROR;
36293 if(!argRequirements->value.data.value.hasValue)
36294 return UA_STATUSCODE_BADINTERNALERROR;
36295 if(argRequirements->value.data.value.value.type != &UA_TYPES[UA_TYPES_ARGUMENT])
36296 return UA_STATUSCODE_BADINTERNALERROR;
36297
36298 /* Verify the number of arguments. A scalar argument value is interpreted as
36299 * an array of length 1. */
36300 size_t argReqsSize = argRequirements->value.data.value.value.arrayLength;
36301 if(UA_Variant_isScalar(v: &argRequirements->value.data.value.value))
36302 argReqsSize = 1;
36303 if(argReqsSize > argsSize)
36304 return UA_STATUSCODE_BADARGUMENTSMISSING;
36305 if(argReqsSize < argsSize)
36306 return UA_STATUSCODE_BADTOOMANYARGUMENTS;
36307
36308 /* Type-check every argument against the definition */
36309 UA_StatusCode retval = UA_STATUSCODE_GOOD;
36310 UA_Argument *argReqs = (UA_Argument*)argRequirements->value.data.value.value.data;
36311 const char *reason;
36312 for(size_t i = 0; i < argReqsSize; ++i) {
36313 if(compatibleValue(server, session, targetDataTypeId: &argReqs[i].dataType, targetValueRank: argReqs[i].valueRank,
36314 targetArrayDimensionsSize: argReqs[i].arrayDimensionsSize, targetArrayDimensions: argReqs[i].arrayDimensions,
36315 value: &args[i], NULL, reason: &reason))
36316 continue;
36317
36318 /* Incompatible value. Try to correct the type if possible. */
36319 adjustValueType(server, value: &args[i], targetDataTypeId: &argReqs[i].dataType);
36320
36321 /* Recheck */
36322 if(!compatibleValue(server, session, targetDataTypeId: &argReqs[i].dataType, targetValueRank: argReqs[i].valueRank,
36323 targetArrayDimensionsSize: argReqs[i].arrayDimensionsSize, targetArrayDimensions: argReqs[i].arrayDimensions,
36324 value: &args[i], NULL, reason: &reason)) {
36325 inputArgumentResults[i] = UA_STATUSCODE_BADTYPEMISMATCH;
36326 retval = UA_STATUSCODE_BADINVALIDARGUMENT;
36327 }
36328 }
36329 return retval;
36330}
36331
36332/* inputArgumentResults has the length request->inputArgumentsSize */
36333static UA_StatusCode
36334validMethodArguments(UA_Server *server, UA_Session *session, const UA_MethodNode *method,
36335 const UA_CallMethodRequest *request,
36336 UA_StatusCode *inputArgumentResults) {
36337 /* Get the input arguments node */
36338 const UA_VariableNode *inputArguments =
36339 getArgumentsVariableNode(server, head: &method->head, withBrowseName: UA_STRING(chars: "InputArguments"));
36340 if(!inputArguments) {
36341 if(request->inputArgumentsSize > 0)
36342 return UA_STATUSCODE_BADTOOMANYARGUMENTS;
36343 return UA_STATUSCODE_GOOD;
36344 }
36345
36346 /* Verify the request */
36347 UA_StatusCode retval =
36348 typeCheckArguments(server, session, argRequirements: inputArguments, argsSize: request->inputArgumentsSize,
36349 args: request->inputArguments, inputArgumentResults);
36350
36351 /* Release the input arguments node */
36352 UA_NODESTORE_RELEASE(server, (const UA_Node*)inputArguments);
36353 return retval;
36354}
36355
36356static const UA_NodeId hasComponentNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}};
36357static const UA_NodeId organizedByNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}};
36358static const UA_String namespaceDiModel = UA_STRING_STATIC("http://opcfoundation.org/UA/DI/");
36359static const UA_NodeId hasTypeDefinitionNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASTYPEDEFINITION}};
36360// ns=0 will be replace dynamically. DI-Spec. 1.01: <UAObjectType NodeId="ns=1;i=1005" BrowseName="1:FunctionalGroupType">
36361static UA_NodeId functionGroupNodeId = {0, UA_NODEIDTYPE_NUMERIC, {.numeric: 1005}};
36362
36363static void
36364callWithMethodAndObject(UA_Server *server, UA_Session *session,
36365 const UA_CallMethodRequest *request, UA_CallMethodResult *result,
36366 const UA_MethodNode *method, const UA_ObjectNode *object) {
36367 /* Verify the object's NodeClass */
36368 if(object->head.nodeClass != UA_NODECLASS_OBJECT &&
36369 object->head.nodeClass != UA_NODECLASS_OBJECTTYPE) {
36370 result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
36371 return;
36372 }
36373
36374 /* Verify the method's NodeClass */
36375 if(method->head.nodeClass != UA_NODECLASS_METHOD) {
36376 result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
36377 return;
36378 }
36379
36380 /* Is there a method to execute? */
36381 if(!method->method) {
36382 result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
36383 return;
36384 }
36385
36386 UA_NodePointer methodP = UA_NodePointer_fromNodeId(id: &request->methodId);
36387
36388 /* Verify method/object relations. Object must have a hasComponent or a
36389 * subtype of hasComponent reference to the method node. Therefore, check
36390 * every reference between the parent object and the method node if there is
36391 * a hasComponent (or subtype) reference */
36392 UA_ReferenceTypeSet hasComponentRefs;
36393 result->statusCode =
36394 referenceTypeIndices(server, refType: &hasComponentNodeId, indices: &hasComponentRefs, true);
36395 if(result->statusCode != UA_STATUSCODE_GOOD)
36396 return;
36397
36398 UA_Boolean found = false;
36399 for(size_t i = 0; i < object->head.referencesSize && !found; ++i) {
36400 const UA_NodeReferenceKind *rk = &object->head.references[i];
36401 if(rk->isInverse)
36402 continue;
36403 if(!UA_ReferenceTypeSet_contains(set: &hasComponentRefs, index: rk->referenceTypeIndex))
36404 continue;
36405 const UA_ReferenceTarget *t = NULL;
36406 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
36407 if(UA_NodePointer_equal(p1: t->targetId, p2: methodP)) {
36408 found = true;
36409 break;
36410 }
36411 }
36412 }
36413
36414 if(!found) {
36415 /* The following ParentObject evaluation is a workaround only to fulfill
36416 * the OPC UA Spec. Part 100 - Devices requirements regarding functional
36417 * groups. Compare OPC UA Spec. Part 100 - Devices, Release 1.02
36418 * - 5.4 FunctionalGroupType
36419 * - B.1 Functional Group Usages
36420 * A functional group is a sub-type of the FolderType and is used to
36421 * organize the Parameters and Methods from the complete set (named
36422 * ParameterSet and MethodSet) in (Functional) groups for instance
36423 * Configuration or Identification. The same Property, Parameter or
36424 * Method can be referenced from more than one FunctionalGroup. */
36425
36426 /* Check whether the DI namespace is available */
36427 size_t foundNamespace = 0;
36428 UA_StatusCode res = getNamespaceByName(server, namespaceUri: namespaceDiModel, foundIndex: &foundNamespace);
36429 if(res != UA_STATUSCODE_GOOD) {
36430 result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
36431 return;
36432 }
36433 functionGroupNodeId.namespaceIndex = (UA_UInt16)foundNamespace;
36434
36435 UA_ReferenceTypeSet hasTypeDefinitionRefs;
36436 result->statusCode =
36437 referenceTypeIndices(server, refType: &hasTypeDefinitionNodeId,
36438 indices: &hasTypeDefinitionRefs, true);
36439 if(result->statusCode != UA_STATUSCODE_GOOD)
36440 return;
36441
36442 /* Search for a HasTypeDefinition (or sub-) reference in the parent object */
36443 for(size_t i = 0; i < object->head.referencesSize && !found; ++i) {
36444 const UA_NodeReferenceKind *rk = &object->head.references[i];
36445 if(rk->isInverse)
36446 continue;
36447 if(!UA_ReferenceTypeSet_contains(set: &hasTypeDefinitionRefs, index: rk->referenceTypeIndex))
36448 continue;
36449
36450 /* Verify that the HasTypeDefinition is equal to FunctionGroupType
36451 * (or sub-type) from the DI model */
36452 const UA_ReferenceTarget *t = NULL;
36453 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
36454 if(!UA_NodePointer_isLocal(np: t->targetId))
36455 continue;
36456
36457 UA_NodeId tmpId = UA_NodePointer_toNodeId(np: t->targetId);
36458 if(!isNodeInTree_singleRef(server, leafNode: &tmpId, nodeToFind: &functionGroupNodeId,
36459 UA_REFERENCETYPEINDEX_HASSUBTYPE))
36460 continue;
36461
36462 /* Search for the called method with reference Organize (or
36463 * sub-type) from the parent object */
36464 for(size_t k = 0; k < object->head.referencesSize && !found; ++k) {
36465 const UA_NodeReferenceKind *rkInner = &object->head.references[k];
36466 if(rkInner->isInverse)
36467 continue;
36468 const UA_NodeId * refId =
36469 UA_NODESTORE_GETREFERENCETYPEID(server, rkInner->referenceTypeIndex);
36470 if(!isNodeInTree_singleRef(server, leafNode: refId, nodeToFind: &organizedByNodeId,
36471 UA_REFERENCETYPEINDEX_HASSUBTYPE))
36472 continue;
36473
36474 const UA_ReferenceTarget *t2 = NULL;
36475 while((t2 = UA_NodeReferenceKind_iterate(rk: rkInner, prev: t2))) {
36476 if(UA_NodePointer_equal(p1: t2->targetId, p2: methodP)) {
36477 found = true;
36478 break;
36479 }
36480 }
36481 }
36482 }
36483 }
36484 if(!found) {
36485 result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
36486 return;
36487 }
36488 }
36489
36490 /* Verify access rights */
36491 UA_Boolean executable = method->executable;
36492 if(session != &server->adminSession) {
36493 UA_UNLOCK(&server->serviceMutex);
36494 executable = executable && server->config.accessControl.
36495 getUserExecutableOnObject(server, &server->config.accessControl, &session->sessionId,
36496 session->sessionHandle, &request->methodId, method->head.context,
36497 &request->objectId, object->head.context);
36498 UA_LOCK(&server->serviceMutex);
36499 }
36500
36501 if(!executable) {
36502 result->statusCode = UA_STATUSCODE_BADNOTEXECUTABLE;
36503 return;
36504 }
36505
36506 /* Allocate the inputArgumentResults array */
36507 result->inputArgumentResults = (UA_StatusCode*)
36508 UA_Array_new(size: request->inputArgumentsSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
36509 if(!result->inputArgumentResults) {
36510 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
36511 return;
36512 }
36513 result->inputArgumentResultsSize = request->inputArgumentsSize;
36514
36515 /* Verify Input Arguments */
36516 result->statusCode = validMethodArguments(server, session, method, request,
36517 inputArgumentResults: result->inputArgumentResults);
36518
36519 /* Return inputArgumentResults only for BADINVALIDARGUMENT */
36520 if(result->statusCode != UA_STATUSCODE_BADINVALIDARGUMENT) {
36521 UA_Array_delete(p: result->inputArgumentResults, size: result->inputArgumentResultsSize,
36522 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
36523 result->inputArgumentResults = NULL;
36524 result->inputArgumentResultsSize = 0;
36525 }
36526
36527 /* Error during type-checking? */
36528 if(result->statusCode != UA_STATUSCODE_GOOD)
36529 return;
36530
36531 /* Get the output arguments node */
36532 const UA_VariableNode *outputArguments =
36533 getArgumentsVariableNode(server, head: &method->head, withBrowseName: UA_STRING(chars: "OutputArguments"));
36534
36535 /* Allocate the output arguments array */
36536 size_t outputArgsSize = 0;
36537 if(outputArguments)
36538 outputArgsSize = outputArguments->value.data.value.value.arrayLength;
36539 result->outputArguments = (UA_Variant*)
36540 UA_Array_new(size: outputArgsSize, type: &UA_TYPES[UA_TYPES_VARIANT]);
36541 if(!result->outputArguments) {
36542 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
36543 return;
36544 }
36545 result->outputArgumentsSize = outputArgsSize;
36546
36547 /* Release the output arguments node */
36548 UA_NODESTORE_RELEASE(server, (const UA_Node*)outputArguments);
36549
36550 /* Call the method */
36551 UA_UNLOCK(&server->serviceMutex);
36552 result->statusCode = method->method(server, &session->sessionId, session->sessionHandle,
36553 &method->head.nodeId, method->head.context,
36554 &object->head.nodeId, object->head.context,
36555 request->inputArgumentsSize, request->inputArguments,
36556 result->outputArgumentsSize, result->outputArguments);
36557 UA_LOCK(&server->serviceMutex);
36558 /* TODO: Verify Output matches the argument definition */
36559}
36560
36561#if UA_MULTITHREADING >= 100
36562
36563static void
36564Operation_CallMethodAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId,
36565 UA_UInt32 requestHandle, size_t opIndex,
36566 UA_CallMethodRequest *opRequest, UA_CallMethodResult *opResult,
36567 UA_AsyncResponse **ar) {
36568 /* Get the method node */
36569 const UA_Node *method = UA_NODESTORE_GET(server, &opRequest->methodId);
36570 if(!method) {
36571 opResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36572 return;
36573 }
36574
36575 /* Get the object node */
36576 const UA_Node *object = UA_NODESTORE_GET(server, &opRequest->objectId);
36577 if(!object) {
36578 opResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36579 UA_NODESTORE_RELEASE(server, method);
36580 return;
36581 }
36582
36583 /* Synchronous execution */
36584 if(!method->methodNode.async) {
36585 callWithMethodAndObject(server, session, opRequest, opResult,
36586 &method->methodNode, &object->objectNode);
36587 goto cleanup;
36588 }
36589
36590 /* <-- Async method call --> */
36591
36592 /* No AsyncResponse allocated so far */
36593 if(!*ar) {
36594 opResult->statusCode =
36595 UA_AsyncManager_createAsyncResponse(&server->asyncManager, server,
36596 &session->sessionId, requestId, requestHandle,
36597 UA_ASYNCOPERATIONTYPE_CALL, ar);
36598 if(opResult->statusCode != UA_STATUSCODE_GOOD)
36599 goto cleanup;
36600 }
36601
36602 /* Create the Async Request to be taken by workers */
36603 opResult->statusCode =
36604 UA_AsyncManager_createAsyncOp(&server->asyncManager,
36605 server, *ar, opIndex, opRequest);
36606
36607 cleanup:
36608 /* Release the method and object node */
36609 UA_NODESTORE_RELEASE(server, method);
36610 UA_NODESTORE_RELEASE(server, object);
36611}
36612
36613void
36614Service_CallAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId,
36615 const UA_CallRequest *request, UA_CallResponse *response,
36616 UA_Boolean *finished) {
36617 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing CallRequestAsync");
36618 if(server->config.maxNodesPerMethodCall != 0 &&
36619 request->methodsToCallSize > server->config.maxNodesPerMethodCall) {
36620 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36621 return;
36622 }
36623
36624 UA_AsyncResponse *ar = NULL;
36625 response->responseHeader.serviceResult =
36626 UA_Server_processServiceOperationsAsync(server, session, requestId,
36627 request->requestHeader.requestHandle,
36628 (UA_AsyncServiceOperation)Operation_CallMethodAsync,
36629 &request->methodsToCallSize, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST],
36630 &response->resultsSize, &UA_TYPES[UA_TYPES_CALLMETHODRESULT], &ar);
36631
36632 if(ar) {
36633 if(ar->opCountdown > 0) {
36634 /* Move all results to the AsyncResponse. The async operation
36635 * results will be overwritten when the workers return results. */
36636 ar->response.callResponse = *response;
36637 UA_CallResponse_init(response);
36638 *finished = false;
36639 } else {
36640 /* If there is a new AsyncResponse, ensure it has at least one
36641 * pending operation */
36642 UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar);
36643 }
36644 }
36645}
36646#endif
36647
36648static void
36649Operation_CallMethod(UA_Server *server, UA_Session *session, void *context,
36650 const UA_CallMethodRequest *request, UA_CallMethodResult *result) {
36651 /* Get the method node */
36652 const UA_Node *method = UA_NODESTORE_GET(server, &request->methodId);
36653 if(!method) {
36654 result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36655 return;
36656 }
36657
36658 /* Get the object node */
36659 const UA_Node *object = UA_NODESTORE_GET(server, &request->objectId);
36660 if(!object) {
36661 result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36662 UA_NODESTORE_RELEASE(server, method);
36663 return;
36664 }
36665
36666 /* Continue with method and object as context */
36667 callWithMethodAndObject(server, session, request, result,
36668 method: &method->methodNode, object: &object->objectNode);
36669
36670 /* Release the method and object node */
36671 UA_NODESTORE_RELEASE(server, method);
36672 UA_NODESTORE_RELEASE(server, object);
36673}
36674
36675void Service_Call(UA_Server *server, UA_Session *session,
36676 const UA_CallRequest *request, UA_CallResponse *response) {
36677 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing CallRequest");
36678 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36679
36680 if(server->config.maxNodesPerMethodCall != 0 &&
36681 request->methodsToCallSize > server->config.maxNodesPerMethodCall) {
36682 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36683 return;
36684 }
36685
36686 response->responseHeader.serviceResult =
36687 UA_Server_processServiceOperations(server, session,
36688 operationCallback: (UA_ServiceOperation)Operation_CallMethod, NULL,
36689 requestOperations: &request->methodsToCallSize, requestOperationsType: &UA_TYPES[UA_TYPES_CALLMETHODREQUEST],
36690 responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
36691}
36692
36693UA_CallMethodResult
36694UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
36695 UA_CallMethodResult result;
36696 UA_CallMethodResult_init(p: &result);
36697 UA_LOCK(&server->serviceMutex);
36698 Operation_CallMethod(server, session: &server->adminSession, NULL, request, result: &result);
36699 UA_UNLOCK(&server->serviceMutex);
36700 return result;
36701}
36702
36703#endif /* UA_ENABLE_METHODCALLS */
36704
36705/**** amalgamated original file "/src/server/ua_services_session.c" ****/
36706
36707/* This Source Code Form is subject to the terms of the Mozilla Public
36708 * License, v. 2.0. If a copy of the MPL was not distributed with this
36709 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
36710 *
36711 * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
36712 * Copyright 2014-2017 (c) Florian Palm
36713 * Copyright 2014-2016 (c) Sten Grüner
36714 * Copyright 2015 (c) Chris Iatrou
36715 * Copyright 2015 (c) Oleksiy Vasylyev
36716 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
36717 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
36718 * Copyright 2019 (c) Kalycito Infotech Private Limited
36719 * Copyright 2018-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
36720 */
36721
36722
36723/* Delayed callback to free the session memory */
36724static void
36725removeSessionCallback(UA_Server *server, session_list_entry *entry) {
36726 UA_LOCK(&server->serviceMutex);
36727 UA_Session_clear(session: &entry->session, server);
36728 UA_UNLOCK(&server->serviceMutex);
36729}
36730
36731void
36732UA_Server_removeSession(UA_Server *server, session_list_entry *sentry,
36733 UA_DiagnosticEvent event) {
36734 UA_Session *session = &sentry->session;
36735
36736 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36737
36738 /* Remove the Subscriptions */
36739#ifdef UA_ENABLE_SUBSCRIPTIONS
36740 UA_Subscription *sub, *tempsub;
36741 TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) {
36742 UA_Subscription_delete(server, sub);
36743 }
36744
36745 UA_PublishResponseEntry *entry;
36746 while((entry = UA_Session_dequeuePublishReq(session))) {
36747 UA_PublishResponse_clear(p: &entry->response);
36748 UA_free(ptr: entry);
36749 }
36750#endif
36751
36752 /* Callback into userland access control */
36753 if(server->config.accessControl.closeSession) {
36754 UA_UNLOCK(&server->serviceMutex);
36755 server->config.accessControl.closeSession(server, &server->config.accessControl,
36756 &session->sessionId, session->sessionHandle);
36757 UA_LOCK(&server->serviceMutex);
36758 }
36759
36760 /* Detach the Session from the SecureChannel */
36761 UA_Session_detachFromSecureChannel(session);
36762
36763 /* Deactivate the session */
36764 if(sentry->session.activated) {
36765 sentry->session.activated = false;
36766 server->activeSessionCount--;
36767 }
36768
36769 /* Detach the session from the session manager and make the capacity
36770 * available */
36771 LIST_REMOVE(sentry, pointers);
36772 server->sessionCount--;
36773
36774 switch(event) {
36775 case UA_DIAGNOSTICEVENT_CLOSE:
36776 case UA_DIAGNOSTICEVENT_PURGE:
36777 break;
36778 case UA_DIAGNOSTICEVENT_TIMEOUT:
36779 server->serverDiagnosticsSummary.sessionTimeoutCount++;
36780 break;
36781 case UA_DIAGNOSTICEVENT_REJECT:
36782 server->serverDiagnosticsSummary.rejectedSessionCount++;
36783 break;
36784 case UA_DIAGNOSTICEVENT_SECURITYREJECT:
36785 server->serverDiagnosticsSummary.securityRejectedSessionCount++;
36786 break;
36787 case UA_DIAGNOSTICEVENT_ABORT:
36788 server->serverDiagnosticsSummary.sessionAbortCount++;
36789 break;
36790 default:
36791 UA_assert(false);
36792 break;
36793 }
36794
36795 /* Add a delayed callback to remove the session when the currently
36796 * scheduled jobs have completed */
36797 sentry->cleanupCallback.callback = (UA_ApplicationCallback)removeSessionCallback;
36798 sentry->cleanupCallback.application = server;
36799 sentry->cleanupCallback.data = sentry;
36800 sentry->cleanupCallback.nextTime = UA_DateTime_nowMonotonic() + 1;
36801 sentry->cleanupCallback.interval = 0; /* Remove the structure */
36802 UA_Timer_addTimerEntry(t: &server->timer, te: &sentry->cleanupCallback, NULL);
36803}
36804
36805UA_StatusCode
36806UA_Server_removeSessionByToken(UA_Server *server, const UA_NodeId *token,
36807 UA_DiagnosticEvent event) {
36808 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36809 session_list_entry *entry;
36810 LIST_FOREACH(entry, &server->sessions, pointers) {
36811 if(UA_NodeId_equal(n1: &entry->session.header.authenticationToken, n2: token)) {
36812 UA_Server_removeSession(server, sentry: entry, event);
36813 return UA_STATUSCODE_GOOD;
36814 }
36815 }
36816 return UA_STATUSCODE_BADSESSIONIDINVALID;
36817}
36818
36819void
36820UA_Server_cleanupSessions(UA_Server *server, UA_DateTime nowMonotonic) {
36821 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36822 session_list_entry *sentry, *temp;
36823 LIST_FOREACH_SAFE(sentry, &server->sessions, pointers, temp) {
36824 /* Session has timed out? */
36825 if(sentry->session.validTill >= nowMonotonic)
36826 continue;
36827 UA_LOG_INFO_SESSION(&server->config.logger, &sentry->session, "Session has timed out");
36828 UA_Server_removeSession(server, sentry, event: UA_DIAGNOSTICEVENT_TIMEOUT);
36829 }
36830}
36831
36832/************/
36833/* Services */
36834/************/
36835
36836UA_Session *
36837getSessionByToken(UA_Server *server, const UA_NodeId *token) {
36838 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36839
36840 session_list_entry *current = NULL;
36841 LIST_FOREACH(current, &server->sessions, pointers) {
36842 /* Token does not match */
36843 if(!UA_NodeId_equal(n1: &current->session.header.authenticationToken, n2: token))
36844 continue;
36845
36846 /* Session has timed out */
36847 if(UA_DateTime_nowMonotonic() > current->session.validTill) {
36848 UA_LOG_INFO_SESSION(&server->config.logger, &current->session,
36849 "Client tries to use a session that has timed out");
36850 return NULL;
36851 }
36852
36853 return &current->session;
36854 }
36855
36856 return NULL;
36857}
36858
36859UA_Session *
36860UA_Server_getSessionById(UA_Server *server, const UA_NodeId *sessionId) {
36861 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36862
36863 session_list_entry *current = NULL;
36864 LIST_FOREACH(current, &server->sessions, pointers) {
36865 /* Token does not match */
36866 if(!UA_NodeId_equal(n1: &current->session.sessionId, n2: sessionId))
36867 continue;
36868
36869 /* Session has timed out */
36870 if(UA_DateTime_nowMonotonic() > current->session.validTill) {
36871 UA_LOG_INFO_SESSION(&server->config.logger, &current->session,
36872 "Client tries to use a session that has timed out");
36873 return NULL;
36874 }
36875
36876 return &current->session;
36877 }
36878
36879 return NULL;
36880}
36881
36882static UA_StatusCode
36883signCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
36884 const UA_CreateSessionRequest *request,
36885 UA_CreateSessionResponse *response) {
36886 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
36887 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
36888 return UA_STATUSCODE_GOOD;
36889
36890 const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
36891 UA_SignatureData *signatureData = &response->serverSignature;
36892
36893 /* Prepare the signature */
36894 size_t signatureSize = securityPolicy->certificateSigningAlgorithm.
36895 getLocalSignatureSize(channel->channelContext);
36896 UA_StatusCode retval = UA_String_copy(src: &securityPolicy->certificateSigningAlgorithm.uri,
36897 dst: &signatureData->algorithm);
36898 retval |= UA_ByteString_allocBuffer(bs: &signatureData->signature, length: signatureSize);
36899 if(retval != UA_STATUSCODE_GOOD)
36900 return retval;
36901
36902 /* Allocate a temp buffer */
36903 size_t dataToSignSize = request->clientCertificate.length + request->clientNonce.length;
36904 UA_ByteString dataToSign;
36905 retval = UA_ByteString_allocBuffer(bs: &dataToSign, length: dataToSignSize);
36906 if(retval != UA_STATUSCODE_GOOD)
36907 return retval; /* signatureData->signature is cleaned up with the response */
36908
36909 /* Sign the signature */
36910 memcpy(dest: dataToSign.data, src: request->clientCertificate.data, n: request->clientCertificate.length);
36911 memcpy(dest: dataToSign.data + request->clientCertificate.length,
36912 src: request->clientNonce.data, n: request->clientNonce.length);
36913 retval = securityPolicy->certificateSigningAlgorithm.
36914 sign(channel->channelContext, &dataToSign, &signatureData->signature);
36915
36916 /* Clean up */
36917 UA_ByteString_clear(p: &dataToSign);
36918 return retval;
36919}
36920
36921/* Creates and adds a session. But it is not yet attached to a secure channel. */
36922UA_StatusCode
36923UA_Server_createSession(UA_Server *server, UA_SecureChannel *channel,
36924 const UA_CreateSessionRequest *request, UA_Session **session) {
36925 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36926
36927 if(server->sessionCount >= server->config.maxSessions) {
36928 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
36929 "Could not create a Session - Server limits reached");
36930 return UA_STATUSCODE_BADTOOMANYSESSIONS;
36931 }
36932
36933 session_list_entry *newentry = (session_list_entry*)
36934 UA_malloc(size: sizeof(session_list_entry));
36935 if(!newentry)
36936 return UA_STATUSCODE_BADOUTOFMEMORY;
36937
36938 /* Initialize the Session */
36939 UA_Session_init(session: &newentry->session);
36940 newentry->session.sessionId = UA_NODEID_GUID(nsIndex: 1, guid: UA_Guid_random());
36941 newentry->session.header.authenticationToken = UA_NODEID_GUID(nsIndex: 1, guid: UA_Guid_random());
36942
36943 newentry->session.timeout = server->config.maxSessionTimeout;
36944 if(request->requestedSessionTimeout <= server->config.maxSessionTimeout &&
36945 request->requestedSessionTimeout > 0)
36946 newentry->session.timeout = request->requestedSessionTimeout;
36947
36948 /* Attach the session to the channel. But don't activate for now. */
36949 if(channel)
36950 UA_Session_attachToSecureChannel(session: &newentry->session, channel);
36951 UA_Session_updateLifetime(session: &newentry->session);
36952
36953 /* Add to the server */
36954 LIST_INSERT_HEAD(&server->sessions, newentry, pointers);
36955 server->sessionCount++;
36956
36957 *session = &newentry->session;
36958 return UA_STATUSCODE_GOOD;
36959}
36960
36961void
36962Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
36963 const UA_CreateSessionRequest *request,
36964 UA_CreateSessionResponse *response) {
36965 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36966 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel, "Trying to create session");
36967
36968 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
36969 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
36970 /* Compare the clientCertificate with the remoteCertificate of the channel.
36971 * Both the clientCertificate of this request and the remoteCertificate
36972 * of the channel may contain a partial or a complete certificate chain.
36973 * The compareCertificate function of the channelModule will compare the
36974 * first certificate of each chain. The end certificate shall be located
36975 * first in the chain according to the OPC UA specification Part 6 (1.04),
36976 * chapter 6.2.3.*/
36977 UA_StatusCode retval = channel->securityPolicy->channelModule.
36978 compareCertificate(channel->channelContext, &request->clientCertificate);
36979 if(retval != UA_STATUSCODE_GOOD) {
36980 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
36981 "The client certificate did not validate");
36982 response->responseHeader.serviceResult = UA_STATUSCODE_BADCERTIFICATEINVALID;
36983 return;
36984 }
36985 }
36986
36987 UA_assert(channel->securityToken.channelId != 0);
36988
36989 if(!UA_ByteString_equal(string1: &channel->securityPolicy->policyUri,
36990 string2: &UA_SECURITY_POLICY_NONE_URI) &&
36991 request->clientNonce.length < 32) {
36992 response->responseHeader.serviceResult = UA_STATUSCODE_BADNONCEINVALID;
36993 return;
36994 }
36995
36996 if(request->clientCertificate.length > 0) {
36997 UA_CertificateVerification *cv = &server->config.certificateVerification;
36998 response->responseHeader.serviceResult =
36999 cv->verifyApplicationURI(cv->context, &request->clientCertificate,
37000 &request->clientDescription.applicationUri);
37001 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37002 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37003 "The client's ApplicationURI did not match the certificate");
37004 server->serverDiagnosticsSummary.securityRejectedSessionCount++;
37005 server->serverDiagnosticsSummary.rejectedSessionCount++;
37006 return;
37007 }
37008 }
37009
37010 UA_Session *newSession = NULL;
37011 response->responseHeader.serviceResult =
37012 UA_Server_createSession(server, channel, request, session: &newSession);
37013 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37014 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37015 "Processing CreateSessionRequest failed");
37016 server->serverDiagnosticsSummary.rejectedSessionCount++;
37017 return;
37018 }
37019
37020 UA_assert(newSession != NULL);
37021
37022 /* Allocate the response */
37023 response->serverEndpoints = (UA_EndpointDescription *)
37024 UA_Array_new(size: server->config.endpointsSize, type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
37025 if(!response->serverEndpoints) {
37026 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
37027 UA_Server_removeSessionByToken(server, token: &newSession->header.authenticationToken,
37028 event: UA_DIAGNOSTICEVENT_REJECT);
37029 return;
37030 }
37031 response->serverEndpointsSize = server->config.endpointsSize;
37032
37033 /* Copy the server's endpointdescriptions into the response */
37034 for(size_t i = 0; i < server->config.endpointsSize; ++i)
37035 response->responseHeader.serviceResult |=
37036 UA_EndpointDescription_copy(src: &server->config.endpoints[i],
37037 dst: &response->serverEndpoints[i]);
37038 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37039 UA_Server_removeSessionByToken(server, token: &newSession->header.authenticationToken,
37040 event: UA_DIAGNOSTICEVENT_REJECT);
37041 return;
37042 }
37043
37044 /* Mirror back the endpointUrl */
37045 for(size_t i = 0; i < response->serverEndpointsSize; ++i) {
37046 UA_String_clear(p: &response->serverEndpoints[i].endpointUrl);
37047 response->responseHeader.serviceResult |=
37048 UA_String_copy(src: &request->endpointUrl,
37049 dst: &response->serverEndpoints[i].endpointUrl);
37050 }
37051
37052 /* Fill the session information */
37053 newSession->maxResponseMessageSize = request->maxResponseMessageSize;
37054 newSession->maxRequestMessageSize = channel->config.localMaxMessageSize;
37055 response->responseHeader.serviceResult |=
37056 UA_ApplicationDescription_copy(src: &request->clientDescription,
37057 dst: &newSession->clientDescription);
37058
37059 /* Prepare the response */
37060 response->sessionId = newSession->sessionId;
37061 response->revisedSessionTimeout = (UA_Double)newSession->timeout;
37062 response->authenticationToken = newSession->header.authenticationToken;
37063 response->responseHeader.serviceResult |=
37064 UA_String_copy(src: &request->sessionName, dst: &newSession->sessionName);
37065
37066#ifdef UA_ENABLE_DIAGNOSTICS
37067 response->responseHeader.serviceResult |=
37068 UA_String_copy(&request->serverUri, &newSession->diagnostics.serverUri);
37069 response->responseHeader.serviceResult |=
37070 UA_String_copy(&request->endpointUrl, &newSession->diagnostics.endpointUrl);
37071#endif
37072
37073 UA_ByteString_init(p: &response->serverCertificate);
37074
37075 if(server->config.endpointsSize > 0)
37076 for(size_t i = 0; i < response->serverEndpointsSize; ++i) {
37077 if(response->serverEndpoints[i].securityMode==channel->securityMode &&
37078 UA_ByteString_equal(string1: &response->serverEndpoints[i].securityPolicyUri,
37079 string2: &channel->securityPolicy->policyUri) &&
37080 UA_String_equal(s1: &response->serverEndpoints[i].endpointUrl,
37081 s2: &request->endpointUrl))
37082 {
37083 response->responseHeader.serviceResult |=
37084 UA_ByteString_copy(src: &response->serverEndpoints[i].serverCertificate,
37085 dst: &response->serverCertificate);
37086 }
37087 }
37088
37089 /* Create a session nonce */
37090 response->responseHeader.serviceResult |= UA_Session_generateNonce(session: newSession);
37091 response->responseHeader.serviceResult |=
37092 UA_ByteString_copy(src: &newSession->serverNonce, dst: &response->serverNonce);
37093
37094 /* Sign the signature */
37095 response->responseHeader.serviceResult |=
37096 signCreateSessionResponse(server, channel, request, response);
37097
37098 /* Failure -> remove the session */
37099 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37100 UA_Server_removeSessionByToken(server, token: &newSession->header.authenticationToken,
37101 event: UA_DIAGNOSTICEVENT_REJECT);
37102 return;
37103 }
37104
37105#ifdef UA_ENABLE_DIAGNOSTICS
37106 newSession->diagnostics.clientConnectionTime = UA_DateTime_now();
37107 newSession->diagnostics.clientLastContactTime =
37108 newSession->diagnostics.clientConnectionTime;
37109
37110 /* Create the object in the information model */
37111 createSessionObject(server, newSession);
37112#endif
37113
37114 UA_LOG_INFO_SESSION(&server->config.logger, newSession, "Session created");
37115}
37116
37117static UA_StatusCode
37118checkSignature(const UA_Server *server, const UA_SecurityPolicy *securityPolicy,
37119 void *channelContext, const UA_ByteString *serverNonce,
37120 const UA_SignatureData *signature) {
37121 /* Check for zero signature length */
37122 if(signature->signature.length == 0)
37123 return UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID;
37124
37125 if(!securityPolicy)
37126 return UA_STATUSCODE_BADINTERNALERROR;
37127
37128 const UA_ByteString *localCertificate = &securityPolicy->localCertificate;
37129 /* Data to verify is calculated by appending the serverNonce to the local certificate */
37130 UA_ByteString dataToVerify;
37131 size_t dataToVerifySize = localCertificate->length + serverNonce->length;
37132 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &dataToVerify, length: dataToVerifySize);
37133 if(retval != UA_STATUSCODE_GOOD)
37134 return retval;
37135
37136 memcpy(dest: dataToVerify.data, src: localCertificate->data, n: localCertificate->length);
37137 memcpy(dest: dataToVerify.data + localCertificate->length,
37138 src: serverNonce->data, n: serverNonce->length);
37139 retval = securityPolicy->certificateSigningAlgorithm.
37140 verify(channelContext, &dataToVerify, &signature->signature);
37141 UA_ByteString_clear(p: &dataToVerify);
37142 return retval;
37143}
37144
37145#ifdef UA_ENABLE_ENCRYPTION
37146
37147static UA_StatusCode
37148decryptPassword(UA_SecurityPolicy *securityPolicy, void *tempChannelContext,
37149 const UA_ByteString *serverNonce, UA_UserNameIdentityToken *userToken) {
37150 UA_SecurityPolicyEncryptionAlgorithm *asymEnc =
37151 &securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm;
37152 if(!UA_String_equal(s1: &userToken->encryptionAlgorithm, s2: &asymEnc->uri))
37153 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37154
37155 UA_UInt32 tokenSecretLength;
37156 UA_ByteString decryptedTokenSecret, tokenServerNonce;
37157 size_t tokenpos = 0;
37158 size_t offset = 0;
37159 if(UA_ByteString_copy(src: &userToken->password, dst: &decryptedTokenSecret) != UA_STATUSCODE_GOOD)
37160 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37161
37162 UA_StatusCode retval = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37163 if(asymEnc->decrypt(tempChannelContext, &decryptedTokenSecret) != UA_STATUSCODE_GOOD)
37164 goto cleanup;
37165
37166 UA_UInt32_decodeBinary(src: &decryptedTokenSecret, offset: &offset, dst: &tokenSecretLength);
37167
37168 /* The decrypted data must be large enough to include the Encrypted Token
37169 * Secret Format and the length field must indicate enough data to include
37170 * the server nonce. */
37171 if(decryptedTokenSecret.length < sizeof(UA_UInt32) + serverNonce->length ||
37172 decryptedTokenSecret.length < sizeof(UA_UInt32) + tokenSecretLength ||
37173 tokenSecretLength < serverNonce->length)
37174 goto cleanup;
37175
37176 /* If the Encrypted Token Secret contains padding, the padding must be
37177 * zeroes according to the 1.04.1 specification errata, chapter 3. */
37178 for(size_t i = sizeof(UA_UInt32) + tokenSecretLength; i < decryptedTokenSecret.length; i++) {
37179 if(decryptedTokenSecret.data[i] != 0)
37180 goto cleanup;
37181 }
37182
37183 /* The server nonce must match according to the 1.04.1 specification errata,
37184 * chapter 3. */
37185 tokenpos = sizeof(UA_UInt32) + tokenSecretLength - serverNonce->length;
37186 tokenServerNonce.length = serverNonce->length;
37187 tokenServerNonce.data = &decryptedTokenSecret.data[tokenpos];
37188 if(!UA_ByteString_equal(string1: serverNonce, string2: &tokenServerNonce))
37189 goto cleanup;
37190
37191 /* The password was decrypted successfully. Replace usertoken with the
37192 * decrypted password. The encryptionAlgorithm and policyId fields are left
37193 * in the UserToken as an indication for the AccessControl plugin that
37194 * evaluates the decrypted content. */
37195 memcpy(dest: userToken->password.data, src: &decryptedTokenSecret.data[sizeof(UA_UInt32)],
37196 n: tokenSecretLength - serverNonce->length);
37197 userToken->password.length = tokenSecretLength - serverNonce->length;
37198 retval = UA_STATUSCODE_GOOD;
37199
37200 cleanup:
37201 UA_ByteString_clear(p: &decryptedTokenSecret);
37202 return retval;
37203}
37204#endif
37205
37206static void
37207selectEndpointAndTokenPolicy(UA_Server *server, UA_SecureChannel *channel,
37208 const UA_ExtensionObject *identityToken,
37209 const UA_EndpointDescription **ed,
37210 const UA_UserTokenPolicy **utp) {
37211 for(size_t i = 0; i < server->config.endpointsSize; ++i) {
37212 const UA_EndpointDescription *desc = &server->config.endpoints[i];
37213
37214 /* Match the Security Mode */
37215 if(desc->securityMode != channel->securityMode)
37216 continue;
37217
37218 /* Match the SecurityPolicy of the endpoint with the current channel */
37219 if(!UA_String_equal(s1: &desc->securityPolicyUri, s2: &channel->securityPolicy->policyUri))
37220 continue;
37221
37222 /* Match the UserTokenType */
37223 const UA_DataType *tokenDataType = identityToken->content.decoded.type;
37224 for(size_t j = 0; j < desc->userIdentityTokensSize; j++) {
37225 const UA_UserTokenPolicy *pol = &desc->userIdentityTokens[j];
37226
37227 /* Part 4, Section 5.6.3.2, Table 17: A NULL or empty
37228 * UserIdentityToken should be treated as Anonymous */
37229 if(identityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY &&
37230 pol->tokenType == UA_USERTOKENTYPE_ANONYMOUS) {
37231 *ed = desc;
37232 *utp = pol;
37233 return;
37234 }
37235
37236 /* Expect decoded content */
37237 if(!tokenDataType)
37238 continue;
37239
37240 if(pol->tokenType == UA_USERTOKENTYPE_ANONYMOUS) {
37241 if(tokenDataType != &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN])
37242 continue;
37243 } else if(pol->tokenType == UA_USERTOKENTYPE_USERNAME) {
37244 if(tokenDataType != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN])
37245 continue;
37246 } else if(pol->tokenType == UA_USERTOKENTYPE_CERTIFICATE) {
37247 if(tokenDataType != &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN])
37248 continue;
37249 } else if(pol->tokenType == UA_USERTOKENTYPE_ISSUEDTOKEN) {
37250 if(tokenDataType != &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN])
37251 continue;
37252 } else {
37253 continue;
37254 }
37255
37256 /* All valid token data types start with a string policyId */
37257 UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
37258 identityToken->content.decoded.data;
37259
37260 if(!UA_String_equal(s1: &pol->policyId, s2: &token->policyId))
37261 continue;
37262
37263 /* Match found */
37264 *ed = desc;
37265 *utp = pol;
37266 return;
37267 }
37268 }
37269}
37270
37271#ifdef UA_ENABLE_DIAGNOSTICS
37272static UA_StatusCode
37273saveClientUserId(const UA_ExtensionObject *userIdentityToken,
37274 UA_SessionSecurityDiagnosticsDataType *diag) {
37275 UA_StatusCode res = UA_STATUSCODE_GOOD;
37276
37277 UA_String_clear(&diag->clientUserIdOfSession);
37278 if(userIdentityToken->encoding != UA_EXTENSIONOBJECT_DECODED)
37279 return UA_STATUSCODE_GOOD;
37280
37281 if(userIdentityToken->content.decoded.type ==
37282 &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
37283 /* String of length 0 */
37284 } else if(userIdentityToken->content.decoded.type ==
37285 &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
37286 const UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken*)
37287 userIdentityToken->content.decoded.data;
37288 res = UA_String_copy(&userToken->userName, &diag->clientUserIdOfSession);
37289 } else if(userIdentityToken->content.decoded.type ==
37290 &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
37291 /* TODO: return the X509 Subject Name of the certificate */
37292 } else {
37293 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37294 }
37295
37296 if(res != UA_STATUSCODE_GOOD)
37297 return res;
37298
37299 return UA_Array_appendCopy((void**)&diag->clientUserIdHistory,
37300 &diag->clientUserIdHistorySize,
37301 &diag->clientUserIdOfSession,
37302 &UA_TYPES[UA_TYPES_STRING]);
37303}
37304#endif
37305
37306
37307/* TODO: Check all of the following: The Server shall verify that the
37308 * Certificate the Client used to create the new SecureChannel is the same as
37309 * the Certificate used to create the original SecureChannel. In addition, the
37310 * Server shall verify that the Client supplied a UserIdentityToken that is
37311 * identical to the token currently associated with the Session. Once the Server
37312 * accepts the new SecureChannel it shall reject requests sent via the old
37313 * SecureChannel. */
37314
37315void
37316Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
37317 const UA_ActivateSessionRequest *request,
37318 UA_ActivateSessionResponse *response) {
37319 const UA_EndpointDescription *ed = NULL;
37320 const UA_UserTokenPolicy *utp = NULL;
37321 UA_String *tmpLocaleIds;
37322 UA_LOCK_ASSERT(&server->serviceMutex, 1);
37323
37324 UA_Session *session = getSessionByToken(server, token: &request->requestHeader.authenticationToken);
37325 if(!session) {
37326 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37327 "ActivateSession: Session not found");
37328 response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
37329 goto rejected;
37330 }
37331
37332 /* Part 4, §5.6.3: When the ActivateSession Service is called for the
37333 * first time then the Server shall reject the request if the
37334 * SecureChannel is not same as the one associated with the
37335 * CreateSession request. Subsequent calls to ActivateSession may be
37336 * associated with different SecureChannels. */
37337 if(!session->activated && session->header.channel != channel) {
37338 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37339 "ActivateSession: The Session has to be initially activated "
37340 "on the SecureChannel that created it");
37341 response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
37342 goto rejected;
37343 }
37344
37345 /* Has the session timed out? */
37346 if(session->validTill < UA_DateTime_nowMonotonic()) {
37347 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37348 "ActivateSession: The Session has timed out");
37349 response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
37350 goto rejected;
37351 }
37352
37353 /* Check the client signature */
37354 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
37355 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
37356 response->responseHeader.serviceResult =
37357 checkSignature(server, securityPolicy: channel->securityPolicy, channelContext: channel->channelContext,
37358 serverNonce: &session->serverNonce, signature: &request->clientSignature);
37359 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37360 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37361 "ActivateSession: Client signature check failed with StatusCode %s",
37362 UA_StatusCode_name(response->responseHeader.serviceResult));
37363 goto securityRejected;
37364 }
37365 }
37366
37367 /* Find the matching Endpoint with UserTokenPolicy */
37368 selectEndpointAndTokenPolicy(server, channel, identityToken: &request->userIdentityToken, ed: &ed, utp: &utp);
37369 if(!ed) {
37370 response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37371 goto rejected;
37372 }
37373
37374 /* If it is a UserNameIdentityToken, the password may be encrypted */
37375 if(utp->tokenType == UA_USERTOKENTYPE_USERNAME) {
37376 UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken *)
37377 request->userIdentityToken.content.decoded.data;
37378
37379 /* If the userTokenPolicy doesn't specify a security policy the security
37380 * policy of the secure channel is used. */
37381 UA_SecurityPolicy* securityPolicy;
37382 if(!utp->securityPolicyUri.data)
37383 securityPolicy = getSecurityPolicyByUri(server, securityPolicyUri: &ed->securityPolicyUri);
37384 else
37385 securityPolicy = getSecurityPolicyByUri(server, securityPolicyUri: &utp->securityPolicyUri);
37386 if(!securityPolicy) {
37387 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
37388 goto securityRejected;
37389 }
37390
37391 /* Test if the encryption algorithm is correctly specified */
37392 if(!UA_String_equal(s1: &userToken->encryptionAlgorithm,
37393 s2: &securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.uri)) {
37394 response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37395 goto securityRejected;
37396 }
37397
37398#ifdef UA_ENABLE_ENCRYPTION
37399 /* Encrypted password? */
37400 if(!UA_String_equal(s1: &securityPolicy->policyUri, s2: &UA_SECURITY_POLICY_NONE_URI)) {
37401 /* Create a temporary channel context if a different SecurityPolicy is
37402 * used for the password from the SecureChannel */
37403 void *tempChannelContext = channel->channelContext;
37404 if(securityPolicy != channel->securityPolicy) {
37405 /* We use our own certificate to create a temporary channel
37406 * context. Because the client does not provide one in a #None
37407 * SecureChannel. We should not need a ChannelContext at all for
37408 * asymmetric decryption where the remote certificate is not
37409 * used. */
37410 UA_UNLOCK(&server->serviceMutex);
37411 response->responseHeader.serviceResult = securityPolicy->channelModule.
37412 newContext(securityPolicy, &securityPolicy->localCertificate,
37413 &tempChannelContext);
37414 UA_LOCK(&server->serviceMutex);
37415 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37416 UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: "
37417 "Failed to create a context for the SecurityPolicy %.*s",
37418 (int)securityPolicy->policyUri.length,
37419 securityPolicy->policyUri.data);
37420 goto securityRejected;
37421 }
37422 }
37423
37424 /* Decrypt */
37425 response->responseHeader.serviceResult =
37426 decryptPassword(securityPolicy, tempChannelContext, serverNonce: &session->serverNonce, userToken);
37427
37428 /* Remove the temporary channel context */
37429 if(securityPolicy != channel->securityPolicy) {
37430 UA_UNLOCK(&server->serviceMutex);
37431 securityPolicy->channelModule.deleteContext(tempChannelContext);
37432 UA_LOCK(&server->serviceMutex);
37433 }
37434 } else if(userToken->encryptionAlgorithm.length != 0) {
37435 /* If SecurityPolicy is None there shall be no EncryptionAlgorithm */
37436 response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37437 goto securityRejected;
37438 }
37439
37440 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37441 UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: "
37442 "Failed to decrypt the password with the StatusCode %s",
37443 UA_StatusCode_name(response->responseHeader.serviceResult));
37444 goto securityRejected;
37445 }
37446#endif
37447 }
37448
37449#ifdef UA_ENABLE_ENCRYPTION
37450 /* If it is a X509IdentityToken, check the userTokenSignature. Note this
37451 * only validates that the user has the corresponding private key for the
37452 * given user cetificate. Checking whether the user certificate is trusted
37453 * has to be implemented in the access control plugin. The entire token is
37454 * forwarded in the call to ActivateSession. */
37455 if(utp->tokenType == UA_USERTOKENTYPE_CERTIFICATE) {
37456 UA_X509IdentityToken* userCertToken = (UA_X509IdentityToken*)
37457 request->userIdentityToken.content.decoded.data;
37458
37459 /* If the userTokenPolicy doesn't specify a security policy the security
37460 * policy of the secure channel is used. */
37461 UA_SecurityPolicy* securityPolicy;
37462 if(!utp->securityPolicyUri.data)
37463 securityPolicy = getSecurityPolicyByUri(server, securityPolicyUri: &ed->securityPolicyUri);
37464 else
37465 securityPolicy = getSecurityPolicyByUri(server, securityPolicyUri: &utp->securityPolicyUri);
37466 if(!securityPolicy) {
37467 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
37468 goto securityRejected;
37469 }
37470
37471 /* We need a channel context with the user certificate in order to reuse
37472 * the signature checking code. */
37473 void *tempChannelContext;
37474 UA_UNLOCK(&server->serviceMutex);
37475 response->responseHeader.serviceResult = securityPolicy->channelModule.
37476 newContext(securityPolicy, &userCertToken->certificateData, &tempChannelContext);
37477 UA_LOCK(&server->serviceMutex);
37478 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37479 UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: "
37480 "Failed to create a context for the SecurityPolicy %.*s",
37481 (int)securityPolicy->policyUri.length,
37482 securityPolicy->policyUri.data);
37483 goto securityRejected;
37484 }
37485
37486 /* Check the user token signature */
37487 response->responseHeader.serviceResult =
37488 checkSignature(server, securityPolicy: channel->securityPolicy, channelContext: tempChannelContext,
37489 serverNonce: &session->serverNonce, signature: &request->userTokenSignature);
37490
37491 /* Delete the temporary channel context */
37492 UA_UNLOCK(&server->serviceMutex);
37493 securityPolicy->channelModule.deleteContext(tempChannelContext);
37494 UA_LOCK(&server->serviceMutex);
37495 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37496 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37497 "ActivateSession: User token signature check failed with StatusCode %s",
37498 UA_StatusCode_name(response->responseHeader.serviceResult));
37499 goto securityRejected;
37500 }
37501 }
37502#endif
37503
37504 /* Callback into userland access control */
37505 UA_UNLOCK(&server->serviceMutex);
37506 response->responseHeader.serviceResult = server->config.accessControl.
37507 activateSession(server, &server->config.accessControl, ed, &channel->remoteCertificate,
37508 &session->sessionId, &request->userIdentityToken, &session->sessionHandle);
37509 UA_LOCK(&server->serviceMutex);
37510 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37511 UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: The AccessControl "
37512 "plugin denied the activation with the StatusCode %s",
37513 UA_StatusCode_name(response->responseHeader.serviceResult));
37514 goto securityRejected;
37515 }
37516
37517 /* Attach the session to the currently used channel if the session isn't
37518 * attached to a channel or if the session is activated on a different
37519 * channel than it is attached to. */
37520 if(!session->header.channel || session->header.channel != channel) {
37521 /* Attach the new SecureChannel, the old channel will be detached if present */
37522 UA_Session_attachToSecureChannel(session, channel);
37523 UA_LOG_INFO_SESSION(&server->config.logger, session,
37524 "ActivateSession: Session attached to new channel");
37525 }
37526
37527 /* Generate a new session nonce for the next time ActivateSession is called */
37528 response->responseHeader.serviceResult = UA_Session_generateNonce(session);
37529 response->responseHeader.serviceResult |=
37530 UA_ByteString_copy(src: &session->serverNonce, dst: &response->serverNonce);
37531 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37532 UA_Session_detachFromSecureChannel(session);
37533 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37534 "ActivateSession: Could not generate the server nonce");
37535 goto rejected;
37536 }
37537
37538 /* Set the locale */
37539 response->responseHeader.serviceResult |=
37540 UA_Array_copy(src: request->localeIds, size: request->localeIdsSize,
37541 dst: (void**)&tmpLocaleIds, type: &UA_TYPES[UA_TYPES_STRING]);
37542 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37543 UA_Session_detachFromSecureChannel(session);
37544 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37545 "ActivateSession: Could not store the Session LocaleIds");
37546 goto rejected;
37547 }
37548 UA_Array_delete(p: session->localeIds, size: session->localeIdsSize,
37549 type: &UA_TYPES[UA_TYPES_STRING]);
37550 session->localeIds = tmpLocaleIds;
37551 session->localeIdsSize = request->localeIdsSize;
37552
37553 UA_Session_updateLifetime(session);
37554
37555 /* Activate the session */
37556 if(!session->activated) {
37557 session->activated = true;
37558 server->activeSessionCount++;
37559 server->serverDiagnosticsSummary.cumulatedSessionCount++;
37560 }
37561
37562#ifdef UA_ENABLE_DIAGNOSTICS
37563 saveClientUserId(&request->userIdentityToken,
37564 &session->securityDiagnostics);
37565 UA_String_clear(&session->securityDiagnostics.authenticationMechanism);
37566 switch(utp->tokenType) {
37567 case UA_USERTOKENTYPE_ANONYMOUS:
37568 session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("Anonymous");
37569 break;
37570 case UA_USERTOKENTYPE_USERNAME:
37571 session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("UserName");
37572 break;
37573 case UA_USERTOKENTYPE_CERTIFICATE:
37574 session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("Certificate");
37575 break;
37576 case UA_USERTOKENTYPE_ISSUEDTOKEN:
37577 session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("IssuedToken");
37578 break;
37579 default: break;
37580 }
37581#endif
37582
37583 UA_LOG_INFO_SESSION(&server->config.logger, session, "ActivateSession: Session activated");
37584 return;
37585
37586securityRejected:
37587 server->serverDiagnosticsSummary.securityRejectedSessionCount++;
37588rejected:
37589 server->serverDiagnosticsSummary.rejectedSessionCount++;
37590}
37591
37592void
37593Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
37594 const UA_CloseSessionRequest *request,
37595 UA_CloseSessionResponse *response) {
37596 UA_LOCK_ASSERT(&server->serviceMutex, 1);
37597
37598 /* Part 4, 5.6.4: When the CloseSession Service is called before the Session
37599 * is successfully activated, the Server shall reject the request if the
37600 * SecureChannel is not the same as the one associated with the
37601 * CreateSession request.
37602 *
37603 * A non-activated Session is already bound to the SecureChannel that
37604 * created the Session. */
37605 UA_Session *session = NULL;
37606 response->responseHeader.serviceResult =
37607 getBoundSession(server, channel, token: &request->requestHeader.authenticationToken, session: &session);
37608 if(!session && response->responseHeader.serviceResult == UA_STATUSCODE_GOOD)
37609 response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
37610 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37611 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37612 "CloseSession: No Session activated to the SecureChannel");
37613 return;
37614 }
37615
37616 UA_assert(session); /* Assured by the previous section */
37617 UA_LOG_INFO_SESSION(&server->config.logger, session, "Closing the Session");
37618
37619#ifdef UA_ENABLE_SUBSCRIPTIONS
37620 /* If Subscriptions are not deleted, detach them from the Session */
37621 if(!request->deleteSubscriptions) {
37622 UA_Subscription *sub, *sub_tmp;
37623 TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, sub_tmp) {
37624 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
37625 "Detaching the Subscription from the Session");
37626 UA_Session_detachSubscription(server, session, sub, true);
37627 }
37628 }
37629#endif
37630
37631 /* Remove the sesison */
37632 response->responseHeader.serviceResult =
37633 UA_Server_removeSessionByToken(server, token: &session->header.authenticationToken,
37634 event: UA_DIAGNOSTICEVENT_CLOSE);
37635}
37636
37637/**** amalgamated original file "/src/server/ua_services_attribute.c" ****/
37638
37639/* This Source Code Form is subject to the terms of the Mozilla Public
37640 * License, v. 2.0. If a copy of the MPL was not distributed with this
37641 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
37642 *
37643 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
37644 * Copyright 2015-2016 (c) Sten Grüner
37645 * Copyright 2014-2017 (c) Florian Palm
37646 * Copyright 2015 (c) Christian Fimmers
37647 * Copyright 2015-2016 (c) Chris Iatrou
37648 * Copyright 2015-2016 (c) Oleksiy Vasylyev
37649 * Copyright 2015 (c) wuyangtang
37650 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
37651 * Copyright 2016 (c) Lorenz Haas
37652 * Copyright 2017 (c) frax2222
37653 * Copyright 2017 (c) Thomas Bender
37654 * Copyright 2017 (c) Julian Grothoff
37655 * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
37656 * Copyright 2017 (c) Henrik Norrman
37657 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
37658 */
37659
37660
37661#ifdef UA_ENABLE_HISTORIZING
37662#endif
37663
37664/******************/
37665/* Access Control */
37666/******************/
37667
37668/* Session for read operations can be NULL. For example for a MonitoredItem
37669 * where the underlying Subscription was detached during CloseSession. */
37670
37671static UA_UInt32
37672getUserWriteMask(UA_Server *server, const UA_Session *session,
37673 const UA_NodeHead *head) {
37674 if(session == &server->adminSession)
37675 return 0xFFFFFFFF; /* the local admin user has all rights */
37676 UA_UInt32 mask = head->writeMask;
37677 UA_UNLOCK(&server->serviceMutex);
37678 mask &= server->config.accessControl.
37679 getUserRightsMask(server, &server->config.accessControl,
37680 session ? &session->sessionId : NULL,
37681 session ? session->sessionHandle : NULL,
37682 &head->nodeId, head->context);
37683 UA_LOCK(&server->serviceMutex);
37684 return mask;
37685}
37686
37687static UA_Byte
37688getAccessLevel(UA_Server *server, const UA_Session *session,
37689 const UA_VariableNode *node) {
37690 if(session == &server->adminSession)
37691 return 0xFF; /* the local admin user has all rights */
37692 return node->accessLevel;
37693}
37694
37695static UA_Byte
37696getUserAccessLevel(UA_Server *server, const UA_Session *session,
37697 const UA_VariableNode *node) {
37698 if(session == &server->adminSession)
37699 return 0xFF; /* the local admin user has all rights */
37700 UA_Byte retval = node->accessLevel;
37701 UA_UNLOCK(&server->serviceMutex);
37702 retval &= server->config.accessControl.
37703 getUserAccessLevel(server, &server->config.accessControl,
37704 session ? &session->sessionId : NULL,
37705 session ? session->sessionHandle : NULL,
37706 &node->head.nodeId, node->head.context);
37707 UA_LOCK(&server->serviceMutex);
37708 return retval;
37709}
37710
37711static UA_Boolean
37712getUserExecutable(UA_Server *server, const UA_Session *session,
37713 const UA_MethodNode *node) {
37714 if(session == &server->adminSession)
37715 return true; /* the local admin user has all rights */
37716 UA_UNLOCK(&server->serviceMutex);
37717 UA_Boolean userExecutable = node->executable;
37718 userExecutable &=
37719 server->config.accessControl.
37720 getUserExecutable(server, &server->config.accessControl,
37721 session ? &session->sessionId : NULL,
37722 session ? session->sessionHandle : NULL,
37723 &node->head.nodeId, node->head.context);
37724 UA_LOCK(&server->serviceMutex);
37725 return userExecutable;
37726}
37727
37728/****************/
37729/* Read Service */
37730/****************/
37731
37732static UA_StatusCode
37733readIsAbstractAttribute(const UA_Node *node, UA_Variant *v) {
37734 const UA_Boolean *isAbstract;
37735 switch(node->head.nodeClass) {
37736 case UA_NODECLASS_REFERENCETYPE:
37737 isAbstract = &node->referenceTypeNode.isAbstract;
37738 break;
37739 case UA_NODECLASS_OBJECTTYPE:
37740 isAbstract = &node->objectTypeNode.isAbstract;
37741 break;
37742 case UA_NODECLASS_VARIABLETYPE:
37743 isAbstract = &node->variableTypeNode.isAbstract;
37744 break;
37745 case UA_NODECLASS_DATATYPE:
37746 isAbstract = &node->dataTypeNode.isAbstract;
37747 break;
37748 default:
37749 return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
37750 }
37751
37752 return UA_Variant_setScalarCopy(v, p: isAbstract, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
37753}
37754
37755static UA_StatusCode
37756readValueAttributeFromNode(UA_Server *server, UA_Session *session,
37757 const UA_VariableNode *vn, UA_DataValue *v,
37758 UA_NumericRange *rangeptr) {
37759 /* Update the value by the user callback */
37760 if(vn->value.data.callback.onRead) {
37761 UA_UNLOCK(&server->serviceMutex);
37762 vn->value.data.callback.onRead(server,
37763 session ? &session->sessionId : NULL,
37764 session ? session->sessionHandle : NULL,
37765 &vn->head.nodeId, vn->head.context, rangeptr,
37766 &vn->value.data.value);
37767 UA_LOCK(&server->serviceMutex);
37768 vn = (const UA_VariableNode*)UA_NODESTORE_GET(server, &vn->head.nodeId);
37769 if(!vn)
37770 return UA_STATUSCODE_BADNODEIDUNKNOWN;
37771 }
37772
37773 /* Set the result */
37774 if(rangeptr)
37775 return UA_Variant_copyRange(src: &vn->value.data.value.value, dst: &v->value, range: *rangeptr);
37776 UA_StatusCode retval = UA_DataValue_copy(src: &vn->value.data.value, dst: v);
37777
37778 /* Clean up */
37779 if(vn->value.data.callback.onRead)
37780 UA_NODESTORE_RELEASE(server, (const UA_Node *)vn);
37781 return retval;
37782}
37783
37784static UA_StatusCode
37785readValueAttributeFromDataSource(UA_Server *server, UA_Session *session,
37786 const UA_VariableNode *vn, UA_DataValue *v,
37787 UA_TimestampsToReturn timestamps,
37788 UA_NumericRange *rangeptr) {
37789 if(!vn->value.dataSource.read)
37790 return UA_STATUSCODE_BADINTERNALERROR;
37791 UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
37792 timestamps == UA_TIMESTAMPSTORETURN_BOTH);
37793 UA_DataValue v2;
37794 UA_DataValue_init(p: &v2);
37795 UA_UNLOCK(&server->serviceMutex);
37796 UA_StatusCode retval = vn->value.dataSource.
37797 read(server,
37798 session ? &session->sessionId : NULL,
37799 session ? session->sessionHandle : NULL,
37800 &vn->head.nodeId, vn->head.context,
37801 sourceTimeStamp, rangeptr, &v2);
37802 UA_LOCK(&server->serviceMutex);
37803 if(v2.hasValue && v2.value.storageType == UA_VARIANT_DATA_NODELETE) {
37804 retval = UA_DataValue_copy(src: &v2, dst: v);
37805 UA_DataValue_clear(p: &v2);
37806 } else {
37807 *v = v2;
37808 }
37809 return retval;
37810}
37811
37812static UA_StatusCode
37813readValueAttributeComplete(UA_Server *server, UA_Session *session,
37814 const UA_VariableNode *vn, UA_TimestampsToReturn timestamps,
37815 const UA_String *indexRange, UA_DataValue *v) {
37816 /* Compute the index range */
37817 UA_NumericRange range;
37818 UA_NumericRange *rangeptr = NULL;
37819 UA_StatusCode retval = UA_STATUSCODE_GOOD;
37820 if(indexRange && indexRange->length > 0) {
37821 retval = UA_NumericRange_parse(range: &range, str: *indexRange);
37822 if(retval != UA_STATUSCODE_GOOD)
37823 return retval;
37824 rangeptr = &range;
37825 }
37826
37827 switch(vn->valueBackend.backendType) {
37828 case UA_VALUEBACKENDTYPE_INTERNAL:
37829 retval = readValueAttributeFromNode(server, session, vn, v, rangeptr);
37830 //TODO change old structure to value backend
37831 break;
37832 case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
37833 retval = readValueAttributeFromDataSource(server, session, vn, v,
37834 timestamps, rangeptr);
37835 //TODO change old structure to value backend
37836 break;
37837 case UA_VALUEBACKENDTYPE_EXTERNAL:
37838 if(vn->valueBackend.backend.external.callback.notificationRead){
37839 retval = vn->valueBackend.backend.external.callback.
37840 notificationRead(server,
37841 session ? &session->sessionId : NULL,
37842 session ? session->sessionHandle : NULL,
37843 &vn->head.nodeId, vn->head.context, rangeptr);
37844 } else {
37845 retval = UA_STATUSCODE_BADNOTREADABLE;
37846 }
37847 if(retval != UA_STATUSCODE_GOOD){
37848 break;
37849 }
37850 /* Set the result */
37851 if(rangeptr)
37852 retval = UA_DataValue_copyVariantRange(
37853 src: *vn->valueBackend.backend.external.value, dst: v, range: *rangeptr);
37854 else
37855 retval = UA_DataValue_copy(src: *vn->valueBackend.backend.external.value, dst: v);
37856 break;
37857 case UA_VALUEBACKENDTYPE_NONE:
37858 /* Read the value */
37859 if(vn->valueSource == UA_VALUESOURCE_DATA)
37860 retval = readValueAttributeFromNode(server, session, vn, v, rangeptr);
37861 else
37862 retval = readValueAttributeFromDataSource(server, session, vn, v,
37863 timestamps, rangeptr);
37864 /* end lagacy */
37865 break;
37866 }
37867
37868 /* Static Variables and VariableTypes have timestamps of "now". Will be set
37869 * below in the absence of predefined timestamps. */
37870 if(vn->head.nodeClass == UA_NODECLASS_VARIABLE) {
37871 if(!vn->isDynamic) {
37872 v->hasServerTimestamp = false;
37873 v->hasSourceTimestamp = false;
37874 }
37875 } else {
37876 v->hasServerTimestamp = false;
37877 v->hasSourceTimestamp = false;
37878 }
37879
37880 /* Clean up */
37881 if(rangeptr)
37882 UA_free(ptr: range.dimensions);
37883 return retval;
37884}
37885
37886UA_StatusCode
37887readValueAttribute(UA_Server *server, UA_Session *session,
37888 const UA_VariableNode *vn, UA_DataValue *v) {
37889 return readValueAttributeComplete(server, session, vn,
37890 timestamps: UA_TIMESTAMPSTORETURN_NEITHER, NULL, v);
37891}
37892
37893static const UA_String binEncoding = {sizeof("Default Binary")-1, (UA_Byte*)"Default Binary"};
37894static const UA_String xmlEncoding = {sizeof("Default XML")-1, (UA_Byte*)"Default XML"};
37895static const UA_String jsonEncoding = {sizeof("Default JSON")-1, (UA_Byte*)"Default JSON"};
37896
37897#define CHECK_NODECLASS(CLASS) \
37898 if(!(node->head.nodeClass & (CLASS))) { \
37899 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; \
37900 break; \
37901 }
37902
37903#ifdef UA_ENABLE_TYPEDESCRIPTION
37904static const UA_DataType *
37905findDataType(const UA_Node *node, const UA_DataTypeArray *customTypes) {
37906 for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
37907 if(UA_NodeId_equal(n1: &UA_TYPES[i].typeId, n2: &node->head.nodeId)) {
37908 return &UA_TYPES[i];
37909 }
37910 }
37911
37912 // lookup custom type
37913 while(customTypes) {
37914 for(size_t i = 0; i < customTypes->typesSize; ++i) {
37915 if(UA_NodeId_equal(n1: &customTypes->types[i].typeId, n2: &node->head.nodeId))
37916 return &customTypes->types[i];
37917 }
37918 customTypes = customTypes->next;
37919 }
37920 return NULL;
37921}
37922
37923static UA_StatusCode
37924getStructureDefinition(const UA_DataType *type, UA_StructureDefinition *def) {
37925 UA_StatusCode retval =
37926 UA_NodeId_copy(src: &type->binaryEncodingId, dst: &def->defaultEncodingId);
37927 if(retval != UA_STATUSCODE_GOOD)
37928 return retval;
37929 switch(type->typeKind) {
37930 case UA_DATATYPEKIND_STRUCTURE:
37931 def->structureType = UA_STRUCTURETYPE_STRUCTURE;
37932 def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STRUCTURE);
37933 break;
37934 case UA_DATATYPEKIND_OPTSTRUCT:
37935 def->structureType = UA_STRUCTURETYPE_STRUCTUREWITHOPTIONALFIELDS;
37936 def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STRUCTURE);
37937 break;
37938 case UA_DATATYPEKIND_UNION:
37939 def->structureType = UA_STRUCTURETYPE_UNION;
37940 def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_UNION);
37941 break;
37942 default:
37943 return UA_STATUSCODE_BADENCODINGERROR;
37944 }
37945 def->fieldsSize = type->membersSize;
37946 def->fields = (UA_StructureField *)
37947 UA_calloc(nmemb: def->fieldsSize, size: sizeof(UA_StructureField));
37948 if(!def->fields) {
37949 UA_NodeId_clear(p: &def->defaultEncodingId);
37950 return UA_STATUSCODE_BADOUTOFMEMORY;
37951 }
37952
37953 for(size_t cnt = 0; cnt < def->fieldsSize; cnt++) {
37954 const UA_DataTypeMember *m = &type->members[cnt];
37955 def->fields[cnt].valueRank = UA_TRUE == m->isArray ? 1 : -1;
37956 def->fields[cnt].arrayDimensions = NULL;
37957 def->fields[cnt].arrayDimensionsSize = 0;
37958 def->fields[cnt].name = UA_STRING(chars: (char *)(uintptr_t)m->memberName);
37959 def->fields[cnt].description.locale = UA_STRING_NULL;
37960 def->fields[cnt].description.text = UA_STRING_NULL;
37961 def->fields[cnt].dataType = m->memberType->typeId;
37962 def->fields[cnt].maxStringLength = 0;
37963 def->fields[cnt].isOptional = m->isOptional;
37964 }
37965 return UA_STATUSCODE_GOOD;
37966}
37967#endif
37968
37969/* Returns a datavalue that may point into the node via the
37970 * UA_VARIANT_DATA_NODELETE tag. Don't access the returned DataValue once the
37971 * node has been released! */
37972void
37973ReadWithNode(const UA_Node *node, UA_Server *server, UA_Session *session,
37974 UA_TimestampsToReturn timestampsToReturn,
37975 const UA_ReadValueId *id, UA_DataValue *v) {
37976 UA_LOG_NODEID_DEBUG(&node->head.nodeId,
37977 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
37978 "Read attribute %"PRIi32 " of Node %.*s",
37979 id->attributeId, (int)nodeIdStr.length,
37980 nodeIdStr.data));
37981
37982 /* Only Binary Encoding is supported */
37983 if(id->dataEncoding.name.length > 0 &&
37984 !UA_String_equal(s1: &binEncoding, s2: &id->dataEncoding.name)) {
37985 if(UA_String_equal(s1: &xmlEncoding, s2: &id->dataEncoding.name) ||
37986 UA_String_equal(s1: &jsonEncoding, s2: &id->dataEncoding.name))
37987 v->status = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED;
37988 else
37989 v->status = UA_STATUSCODE_BADDATAENCODINGINVALID;
37990 v->hasStatus = true;
37991 return;
37992 }
37993
37994 /* Index range for an attribute other than value */
37995 if(id->indexRange.length > 0 && id->attributeId != UA_ATTRIBUTEID_VALUE) {
37996 v->hasStatus = true;
37997 v->status = UA_STATUSCODE_BADINDEXRANGENODATA;
37998 return;
37999 }
38000
38001 /* Read the attribute */
38002 UA_StatusCode retval = UA_STATUSCODE_GOOD;
38003 switch(id->attributeId) {
38004 case UA_ATTRIBUTEID_NODEID:
38005 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.nodeId,
38006 type: &UA_TYPES[UA_TYPES_NODEID]);
38007 break;
38008 case UA_ATTRIBUTEID_NODECLASS:
38009 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.nodeClass,
38010 type: &UA_TYPES[UA_TYPES_NODECLASS]);
38011 break;
38012 case UA_ATTRIBUTEID_BROWSENAME:
38013 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.browseName,
38014 type: &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
38015 break;
38016 case UA_ATTRIBUTEID_DISPLAYNAME:
38017 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.displayName,
38018 type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
38019 break;
38020 case UA_ATTRIBUTEID_DESCRIPTION:
38021 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.description,
38022 type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
38023 break;
38024 case UA_ATTRIBUTEID_WRITEMASK:
38025 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.writeMask,
38026 type: &UA_TYPES[UA_TYPES_UINT32]);
38027 break;
38028 case UA_ATTRIBUTEID_USERWRITEMASK: {
38029 UA_UInt32 userWriteMask = getUserWriteMask(server, session, head: &node->head);
38030 retval = UA_Variant_setScalarCopy(v: &v->value, p: &userWriteMask,
38031 type: &UA_TYPES[UA_TYPES_UINT32]);
38032 break; }
38033 case UA_ATTRIBUTEID_ISABSTRACT:
38034 retval = readIsAbstractAttribute(node, v: &v->value);
38035 break;
38036 case UA_ATTRIBUTEID_SYMMETRIC:
38037 CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
38038 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->referenceTypeNode.symmetric,
38039 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38040 break;
38041 case UA_ATTRIBUTEID_INVERSENAME:
38042 CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
38043 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->referenceTypeNode.inverseName,
38044 type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
38045 break;
38046 case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
38047 CHECK_NODECLASS(UA_NODECLASS_VIEW);
38048 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->viewNode.containsNoLoops,
38049 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38050 break;
38051 case UA_ATTRIBUTEID_EVENTNOTIFIER:
38052 CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
38053 if(node->head.nodeClass == UA_NODECLASS_VIEW) {
38054 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->viewNode.eventNotifier,
38055 type: &UA_TYPES[UA_TYPES_BYTE]);
38056 } else {
38057 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->objectNode.eventNotifier,
38058 type: &UA_TYPES[UA_TYPES_BYTE]);
38059 }
38060 break;
38061 case UA_ATTRIBUTEID_VALUE: {
38062 CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
38063 /* VariableTypes don't have the AccessLevel concept. Always allow
38064 * reading the value. */
38065 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
38066 /* The access to a value variable is granted via the AccessLevel
38067 * and UserAccessLevel attributes */
38068 UA_Byte accessLevel = getAccessLevel(server, session, node: &node->variableNode);
38069 if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) {
38070 retval = UA_STATUSCODE_BADNOTREADABLE;
38071 break;
38072 }
38073 accessLevel = getUserAccessLevel(server, session, node: &node->variableNode);
38074 if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) {
38075 retval = UA_STATUSCODE_BADUSERACCESSDENIED;
38076 break;
38077 }
38078 }
38079 retval = readValueAttributeComplete(server, session, vn: &node->variableNode,
38080 timestamps: timestampsToReturn, indexRange: &id->indexRange, v);
38081 break;
38082 }
38083 case UA_ATTRIBUTEID_DATATYPE:
38084 CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
38085 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableTypeNode.dataType,
38086 type: &UA_TYPES[UA_TYPES_NODEID]);
38087 break;
38088 case UA_ATTRIBUTEID_VALUERANK:
38089 CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
38090 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableTypeNode.valueRank,
38091 type: &UA_TYPES[UA_TYPES_INT32]);
38092 break;
38093 case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
38094 CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
38095 retval = UA_Variant_setArrayCopy(v: &v->value, array: node->variableTypeNode.arrayDimensions,
38096 arraySize: node->variableTypeNode.arrayDimensionsSize,
38097 type: &UA_TYPES[UA_TYPES_UINT32]);
38098 break;
38099 case UA_ATTRIBUTEID_ACCESSLEVEL:
38100 CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
38101 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableNode.accessLevel,
38102 type: &UA_TYPES[UA_TYPES_BYTE]);
38103 break;
38104 case UA_ATTRIBUTEID_USERACCESSLEVEL: {
38105 CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
38106 UA_Byte userAccessLevel = getUserAccessLevel(server, session, node: &node->variableNode);
38107 retval = UA_Variant_setScalarCopy(v: &v->value, p: &userAccessLevel,
38108 type: &UA_TYPES[UA_TYPES_BYTE]);
38109 break; }
38110 case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
38111 CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
38112 retval = UA_Variant_setScalarCopy(v: &v->value,
38113 p: &node->variableNode.minimumSamplingInterval,
38114 type: &UA_TYPES[UA_TYPES_DOUBLE]);
38115 break;
38116 case UA_ATTRIBUTEID_HISTORIZING:
38117 CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
38118 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableNode.historizing,
38119 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38120 break;
38121 case UA_ATTRIBUTEID_EXECUTABLE:
38122 CHECK_NODECLASS(UA_NODECLASS_METHOD);
38123 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->methodNode.executable,
38124 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38125 break;
38126 case UA_ATTRIBUTEID_USEREXECUTABLE: {
38127 CHECK_NODECLASS(UA_NODECLASS_METHOD);
38128 UA_Boolean userExecutable =
38129 getUserExecutable(server, session, node: &node->methodNode);
38130 retval = UA_Variant_setScalarCopy(v: &v->value, p: &userExecutable,
38131 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38132 break; }
38133 case UA_ATTRIBUTEID_DATATYPEDEFINITION: {
38134 CHECK_NODECLASS(UA_NODECLASS_DATATYPE);
38135
38136#ifdef UA_ENABLE_TYPEDESCRIPTION
38137 const UA_DataType *type =
38138 findDataType(node, customTypes: server->config.customDataTypes);
38139 if(!type) {
38140 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
38141 break;
38142 }
38143
38144 if(UA_DATATYPEKIND_STRUCTURE == type->typeKind ||
38145 UA_DATATYPEKIND_OPTSTRUCT == type->typeKind ||
38146 UA_DATATYPEKIND_UNION == type->typeKind) {
38147 UA_StructureDefinition def;
38148 retval = getStructureDefinition(type, def: &def);
38149 if(UA_STATUSCODE_GOOD!=retval)
38150 break;
38151 retval = UA_Variant_setScalarCopy(v: &v->value, p: &def,
38152 type: &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION]);
38153 UA_free(ptr: def.fields);
38154 break;
38155 }
38156#endif
38157 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
38158 break; }
38159 default:
38160 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
38161 }
38162
38163 if(retval != UA_STATUSCODE_GOOD) {
38164 /* Reading has failed but can not return because we may need to add timestamp */
38165 v->hasStatus = true;
38166 v->status = retval;
38167 } else {
38168 v->hasValue = true;
38169 }
38170
38171 /* Create server timestamp */
38172 if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER ||
38173 timestampsToReturn == UA_TIMESTAMPSTORETURN_BOTH) {
38174 if(!v->hasServerTimestamp) {
38175 v->serverTimestamp = UA_DateTime_now();
38176 v->hasServerTimestamp = true;
38177 }
38178 } else {
38179 /* In case the ServerTimestamp has been set manually */
38180 v->hasServerTimestamp = false;
38181 }
38182
38183 /* Handle source time stamp */
38184 if(id->attributeId == UA_ATTRIBUTEID_VALUE) {
38185 if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER ||
38186 timestampsToReturn == UA_TIMESTAMPSTORETURN_NEITHER) {
38187 v->hasSourceTimestamp = false;
38188 v->hasSourcePicoseconds = false;
38189 } else if(!v->hasSourceTimestamp) {
38190 v->sourceTimestamp = UA_DateTime_now();
38191 v->hasSourceTimestamp = true;
38192 }
38193 }
38194}
38195
38196static void
38197Operation_Read(UA_Server *server, UA_Session *session, UA_ReadRequest *request,
38198 UA_ReadValueId *rvi, UA_DataValue *result) {
38199 /* Get the node */
38200 const UA_Node *node = UA_NODESTORE_GET(server, &rvi->nodeId);
38201
38202 /* Perform the read operation */
38203 if(node) {
38204 ReadWithNode(node, server, session, timestampsToReturn: request->timestampsToReturn, id: rvi, v: result);
38205 UA_NODESTORE_RELEASE(server, node);
38206 } else {
38207 result->hasStatus = true;
38208 result->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
38209 }
38210}
38211
38212void
38213Service_Read(UA_Server *server, UA_Session *session,
38214 const UA_ReadRequest *request, UA_ReadResponse *response) {
38215 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing ReadRequest");
38216 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38217
38218 /* Check if the timestampstoreturn is valid */
38219 if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
38220 response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
38221 return;
38222 }
38223
38224 /* Check if maxAge is valid */
38225 if(request->maxAge < 0) {
38226 response->responseHeader.serviceResult = UA_STATUSCODE_BADMAXAGEINVALID;
38227 return;
38228 }
38229
38230 /* Check if there are too many operations */
38231 if(server->config.maxNodesPerRead != 0 &&
38232 request->nodesToReadSize > server->config.maxNodesPerRead) {
38233 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
38234 return;
38235 }
38236
38237 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38238
38239 response->responseHeader.serviceResult =
38240 UA_Server_processServiceOperations(server, session,
38241 operationCallback: (UA_ServiceOperation)Operation_Read,
38242 context: request, requestOperations: &request->nodesToReadSize,
38243 requestOperationsType: &UA_TYPES[UA_TYPES_READVALUEID],
38244 responseOperations: &response->resultsSize,
38245 responseOperationsType: &UA_TYPES[UA_TYPES_DATAVALUE]);
38246}
38247
38248UA_DataValue
38249UA_Server_readWithSession(UA_Server *server, UA_Session *session,
38250 const UA_ReadValueId *item,
38251 UA_TimestampsToReturn timestampsToReturn) {
38252 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38253
38254 UA_DataValue dv;
38255 UA_DataValue_init(p: &dv);
38256
38257 /* Get the node */
38258 const UA_Node *node = UA_NODESTORE_GET(server, &item->nodeId);
38259 if(!node) {
38260 dv.hasStatus = true;
38261 dv.status = UA_STATUSCODE_BADNODEIDUNKNOWN;
38262 return dv;
38263 }
38264
38265 /* Perform the read operation */
38266 ReadWithNode(node, server, session, timestampsToReturn, id: item, v: &dv);
38267
38268 /* Release the node and return */
38269 UA_NODESTORE_RELEASE(server, node);
38270 return dv;
38271}
38272
38273UA_DataValue
38274readAttribute(UA_Server *server, const UA_ReadValueId *item,
38275 UA_TimestampsToReturn timestamps) {
38276 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38277 return UA_Server_readWithSession(server, session: &server->adminSession, item, timestampsToReturn: timestamps);
38278}
38279
38280UA_StatusCode
38281readWithReadValue(UA_Server *server, const UA_NodeId *nodeId,
38282 const UA_AttributeId attributeId, void *v) {
38283 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38284
38285 /* Call the read service */
38286 UA_ReadValueId item;
38287 UA_ReadValueId_init(p: &item);
38288 item.nodeId = *nodeId;
38289 item.attributeId = attributeId;
38290 UA_DataValue dv = readAttribute(server, item: &item, timestamps: UA_TIMESTAMPSTORETURN_NEITHER);
38291
38292 /* Check the return value */
38293 UA_StatusCode retval = UA_STATUSCODE_GOOD;
38294 if(dv.hasStatus)
38295 retval = dv.status;
38296 else if(!dv.hasValue)
38297 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
38298 if(retval != UA_STATUSCODE_GOOD) {
38299 UA_DataValue_clear(p: &dv);
38300 return retval;
38301 }
38302
38303 if(attributeId == UA_ATTRIBUTEID_VALUE ||
38304 attributeId == UA_ATTRIBUTEID_ARRAYDIMENSIONS) {
38305 /* Return the entire variant */
38306 memcpy(dest: v, src: &dv.value, n: sizeof(UA_Variant));
38307 } else {
38308 /* Return the variant content only */
38309 memcpy(dest: v, src: dv.value.data, n: dv.value.type->memSize);
38310 UA_free(ptr: dv.value.data);
38311 }
38312 return retval;
38313}
38314
38315/* Exposes the Read service to local users */
38316UA_DataValue
38317UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
38318 UA_TimestampsToReturn timestamps) {
38319 UA_LOCK(&server->serviceMutex);
38320 UA_DataValue dv = readAttribute(server, item, timestamps);
38321 UA_UNLOCK(&server->serviceMutex);
38322 return dv;
38323}
38324
38325/* Used in inline functions exposing the Read service with more syntactic sugar
38326 * for individual attributes */
38327UA_StatusCode
38328__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
38329 const UA_AttributeId attributeId, void *v) {
38330 UA_LOCK(&server->serviceMutex);
38331 UA_StatusCode retval = readWithReadValue(server, nodeId, attributeId, v);
38332 UA_UNLOCK(&server->serviceMutex);
38333 return retval;
38334}
38335
38336UA_StatusCode
38337readObjectProperty(UA_Server *server, const UA_NodeId objectId,
38338 const UA_QualifiedName propertyName,
38339 UA_Variant *value) {
38340 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38341
38342 /* Create a BrowsePath to get the target NodeId */
38343 UA_RelativePathElement rpe;
38344 UA_RelativePathElement_init(p: &rpe);
38345 rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
38346 rpe.isInverse = false;
38347 rpe.includeSubtypes = false;
38348 rpe.targetName = propertyName;
38349
38350 UA_BrowsePath bp;
38351 UA_BrowsePath_init(p: &bp);
38352 bp.startingNode = objectId;
38353 bp.relativePath.elementsSize = 1;
38354 bp.relativePath.elements = &rpe;
38355
38356 UA_StatusCode retval;
38357 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp);
38358 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
38359 retval = bpr.statusCode;
38360 UA_BrowsePathResult_clear(p: &bpr);
38361 return retval;
38362 }
38363
38364 /* Use the first result from the BrowsePath */
38365 retval = readWithReadValue(server, nodeId: &bpr.targets[0].targetId.nodeId,
38366 attributeId: UA_ATTRIBUTEID_VALUE, v: value);
38367
38368 UA_BrowsePathResult_clear(p: &bpr);
38369 return retval;
38370}
38371
38372
38373UA_StatusCode
38374UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId,
38375 const UA_QualifiedName propertyName,
38376 UA_Variant *value) {
38377 UA_LOCK(&server->serviceMutex);
38378 UA_StatusCode retval = readObjectProperty(server, objectId, propertyName, value);
38379 UA_UNLOCK(&server->serviceMutex);
38380 return retval;
38381}
38382
38383/*****************/
38384/* Type Checking */
38385/*****************/
38386
38387static UA_DataTypeKind
38388typeEquivalence(const UA_DataType *t) {
38389 UA_DataTypeKind k = (UA_DataTypeKind)t->typeKind;
38390 if(k == UA_DATATYPEKIND_ENUM)
38391 return UA_DATATYPEKIND_INT32;
38392 return k;
38393}
38394
38395static const UA_NodeId enumNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ENUMERATION}};
38396
38397UA_Boolean
38398compatibleValueDataType(UA_Server *server, const UA_DataType *dataType,
38399 const UA_NodeId *constraintDataType) {
38400 if(compatibleDataTypes(server, dataType: &dataType->typeId, constraintDataType))
38401 return true;
38402
38403 /* For actual values, the constraint DataType may be a subtype of the
38404 * DataType of the value. E.g. UtcTime is subtype of DateTime. But it still
38405 * is a DateTime value when transferred over the wire. */
38406 if(isNodeInTree_singleRef(server, leafNode: constraintDataType, nodeToFind: &dataType->typeId,
38407 UA_REFERENCETYPEINDEX_HASSUBTYPE))
38408 return true;
38409
38410 return false;
38411}
38412
38413UA_Boolean
38414compatibleDataTypes(UA_Server *server, const UA_NodeId *dataType,
38415 const UA_NodeId *constraintDataType) {
38416 /* Do not allow empty datatypes */
38417 if(UA_NodeId_isNull(p: dataType))
38418 return false;
38419
38420 /* No constraint or Variant / BaseDataType which allows any content */
38421 if(UA_NodeId_isNull(p: constraintDataType) ||
38422 UA_NodeId_equal(n1: constraintDataType, n2: &UA_TYPES[UA_TYPES_VARIANT].typeId))
38423 return true;
38424
38425 /* Same datatypes */
38426 if(UA_NodeId_equal(n1: dataType, n2: constraintDataType))
38427 return true;
38428
38429 /* Is the DataType a subtype of the constraint type? */
38430 if(isNodeInTree_singleRef(server, leafNode: dataType, nodeToFind: constraintDataType,
38431 UA_REFERENCETYPEINDEX_HASSUBTYPE))
38432 return true;
38433
38434 /* The constraint is an enum -> allow writing Int32 */
38435 if(UA_NodeId_equal(n1: dataType, n2: &UA_TYPES[UA_TYPES_INT32].typeId) &&
38436 isNodeInTree_singleRef(server, leafNode: constraintDataType, nodeToFind: &enumNodeId,
38437 UA_REFERENCETYPEINDEX_HASSUBTYPE))
38438 return true;
38439
38440 return false;
38441}
38442
38443/* Test whether a ValueRank and the given arraydimensions are compatible.
38444 *
38445 * 5.6.2 Variable NodeClass: If the maximum is unknown the value shall be 0. The
38446 * number of elements shall be equal to the value of the ValueRank Attribute.
38447 * This Attribute shall be null if ValueRank <= 0. */
38448UA_Boolean
38449compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session,
38450 UA_Int32 valueRank, size_t arrayDimensionsSize) {
38451 /* ValueRank invalid */
38452 if(valueRank < UA_VALUERANK_SCALAR_OR_ONE_DIMENSION) {
38453 UA_LOG_INFO_SESSION(&server->config.logger, session,
38454 "The ValueRank is invalid (< -3)");
38455 return false;
38456 }
38457
38458 /* case -3, UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: the value can be a scalar
38459 * or a one dimensional array
38460 * case -2, UA_VALUERANK_ANY: the value can be a scalar or an array with any
38461 * number of dimensions
38462 * case -1, UA_VALUERANK_SCALAR: the value is a scalar
38463 * case 0, UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: the value is an array with
38464 * one or more dimensions */
38465 if(valueRank <= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS) {
38466 if(arrayDimensionsSize > 0) {
38467 UA_LOG_INFO_SESSION(&server->config.logger, session,
38468 "No ArrayDimensions can be defined for a ValueRank <= 0");
38469 return false;
38470 }
38471 return true;
38472 }
38473
38474 /* case >= 1, UA_VALUERANK_ONE_DIMENSION: the value is an array with the
38475 specified number of dimensions */
38476 if(arrayDimensionsSize != (size_t)valueRank) {
38477 UA_LOG_INFO_SESSION(&server->config.logger, session,
38478 "The number of ArrayDimensions is not equal to "
38479 "the (positive) ValueRank");
38480 return false;
38481 }
38482 return true;
38483}
38484
38485UA_Boolean
38486compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank) {
38487 /* Check if the valuerank of the variabletype allows the change. */
38488 switch(constraintValueRank) {
38489 case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* the value can be a scalar or a
38490 one dimensional array */
38491 if(valueRank != UA_VALUERANK_SCALAR && valueRank != UA_VALUERANK_ONE_DIMENSION)
38492 return false;
38493 break;
38494 case UA_VALUERANK_ANY: /* the value can be a scalar or an array with any
38495 number of dimensions */
38496 break;
38497 case UA_VALUERANK_SCALAR: /* the value is a scalar */
38498 if(valueRank != UA_VALUERANK_SCALAR)
38499 return false;
38500 break;
38501 case UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: /* the value is an array with one
38502 or more dimensions */
38503 if(valueRank < (UA_Int32) UA_VALUERANK_ONE_OR_MORE_DIMENSIONS)
38504 return false;
38505 break;
38506 default: /* >= 1: the value is an array with the specified number of
38507 dimensions */
38508 if(valueRank != constraintValueRank)
38509 return false;
38510 break;
38511 }
38512 return true;
38513}
38514
38515/* Check if the ValueRank allows for the value dimension. This is more
38516 * permissive than checking for the ArrayDimensions attribute. Because the value
38517 * can have dimensions if the ValueRank < 0 */
38518static UA_Boolean
38519compatibleValueRankValue(UA_Int32 valueRank, const UA_Variant *value) {
38520 /* Invalid ValueRank */
38521 if(valueRank < UA_VALUERANK_SCALAR_OR_ONE_DIMENSION)
38522 return false;
38523
38524 /* Empty arrays (-1) always match */
38525 if(!value->data)
38526 return true;
38527
38528 size_t arrayDims = value->arrayDimensionsSize;
38529 if(arrayDims == 0 && !UA_Variant_isScalar(v: value))
38530 arrayDims = 1; /* array but no arraydimensions -> implicit array dimension 1 */
38531
38532 /* We cannot simply use compatibleValueRankArrayDimensions since we can have
38533 * defined ArrayDimensions for the value if the ValueRank is -2 */
38534 switch(valueRank) {
38535 case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* The value can be a scalar or a
38536 one dimensional array */
38537 return (arrayDims <= 1);
38538 case UA_VALUERANK_ANY: /* The value can be a scalar or an array with any
38539 number of dimensions */
38540 return true;
38541 case UA_VALUERANK_SCALAR: /* The value is a scalar */
38542 return (arrayDims == 0);
38543 case UA_VALUERANK_ONE_OR_MORE_DIMENSIONS:
38544 return (arrayDims >= 1);
38545 default:
38546 break;
38547 }
38548
38549 UA_assert(valueRank >= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS);
38550
38551 /* case 0: the value is an array with one or more dimensions */
38552 return (arrayDims == (UA_UInt32)valueRank);
38553}
38554
38555UA_Boolean
38556compatibleArrayDimensions(size_t constraintArrayDimensionsSize,
38557 const UA_UInt32 *constraintArrayDimensions,
38558 size_t testArrayDimensionsSize,
38559 const UA_UInt32 *testArrayDimensions) {
38560 /* No array dimensions defined -> everything is permitted if the value rank fits */
38561 if(constraintArrayDimensionsSize == 0)
38562 return true;
38563
38564 /* Dimension count must match */
38565 if(testArrayDimensionsSize != constraintArrayDimensionsSize)
38566 return false;
38567
38568 /* Dimension lengths must not be larger than the constraint. Zero in the
38569 * constraint indicates a wildcard. */
38570 for(size_t i = 0; i < constraintArrayDimensionsSize; ++i) {
38571 if(constraintArrayDimensions[i] < testArrayDimensions[i] &&
38572 constraintArrayDimensions[i] != 0)
38573 return false;
38574 }
38575 return true;
38576}
38577
38578UA_Boolean
38579compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimensionsSize,
38580 const UA_UInt32 *targetArrayDimensions) {
38581 size_t valueArrayDimensionsSize = value->arrayDimensionsSize;
38582 UA_UInt32 *valueArrayDimensions = value->arrayDimensions;
38583 UA_UInt32 tempArrayDimensions;
38584 if(!valueArrayDimensions && !UA_Variant_isScalar(v: value)) {
38585 valueArrayDimensionsSize = 1;
38586 tempArrayDimensions = (UA_UInt32)value->arrayLength;
38587 valueArrayDimensions = &tempArrayDimensions;
38588 }
38589 UA_assert(valueArrayDimensionsSize == 0 || valueArrayDimensions != NULL);
38590 return compatibleArrayDimensions(constraintArrayDimensionsSize: targetArrayDimensionsSize, constraintArrayDimensions: targetArrayDimensions,
38591 testArrayDimensionsSize: valueArrayDimensionsSize, testArrayDimensions: valueArrayDimensions);
38592}
38593
38594const char *reason_EmptyType = "Empty value only allowed for BaseDataType";
38595const char *reason_ValueDataType = "DataType of the value is incompatible";
38596const char *reason_ValueArrayDimensions = "ArrayDimensions of the value are incompatible";
38597const char *reason_ValueValueRank = "ValueRank of the value is incompatible";
38598
38599UA_Boolean
38600compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetDataTypeId,
38601 UA_Int32 targetValueRank, size_t targetArrayDimensionsSize,
38602 const UA_UInt32 *targetArrayDimensions, const UA_Variant *value,
38603 const UA_NumericRange *range, const char **reason) {
38604 /* Empty value */
38605 if(!value->type) {
38606 /* Empty value is allowed for BaseDataType */
38607 if(UA_NodeId_equal(n1: targetDataTypeId, n2: &UA_TYPES[UA_TYPES_VARIANT].typeId) ||
38608 UA_NodeId_equal(n1: targetDataTypeId, n2: &UA_NODEID_NULL))
38609 return true;
38610
38611 /* Ignore if that is configured */
38612 if(server->bootstrapNS0 ||
38613 server->config.allowEmptyVariables == UA_RULEHANDLING_ACCEPT)
38614 return true;
38615
38616 UA_LOG_INFO_SESSION(&server->config.logger, session,
38617 "Only Variables with data type BaseDataType "
38618 "can contain an empty value");
38619
38620 /* Ignore if that is configured */
38621 if(server->config.allowEmptyVariables == UA_RULEHANDLING_WARN)
38622 return true;
38623
38624 /* Default handling is to abort */
38625 *reason = reason_EmptyType;
38626 return false;
38627 }
38628
38629 /* Is the datatype compatible? */
38630 if(!compatibleValueDataType(server, dataType: value->type, constraintDataType: targetDataTypeId)) {
38631 *reason = reason_ValueDataType;
38632 return false;
38633 }
38634
38635 /* Array dimensions are checked later when writing the range */
38636 if(range)
38637 return true;
38638
38639 /* See if the array dimensions match. */
38640 if(!compatibleValueArrayDimensions(value, targetArrayDimensionsSize,
38641 targetArrayDimensions)) {
38642 *reason = reason_ValueArrayDimensions;
38643 return false;
38644 }
38645
38646 /* Check if the valuerank allows for the value dimension */
38647 if(!compatibleValueRankValue(valueRank: targetValueRank, value)) {
38648 *reason = reason_ValueValueRank;
38649 return false;
38650 }
38651
38652 return true;
38653}
38654
38655/*****************/
38656/* Write Service */
38657/*****************/
38658
38659void
38660adjustValueType(UA_Server *server, UA_Variant *value,
38661 const UA_NodeId *targetDataTypeId) {
38662 /* If the value is empty, there is nothing we can do here */
38663 if(!value->type)
38664 return;
38665
38666 const UA_DataType *targetDataType = UA_findDataType(typeId: targetDataTypeId);
38667 if(!targetDataType)
38668 return;
38669
38670 /* A string is written to a byte array. the valuerank and array dimensions
38671 * are checked later */
38672 if(targetDataType == &UA_TYPES[UA_TYPES_BYTE] &&
38673 value->type == &UA_TYPES[UA_TYPES_BYTESTRING] &&
38674 UA_Variant_isScalar(v: value)) {
38675 UA_ByteString *str = (UA_ByteString*)value->data;
38676 value->type = &UA_TYPES[UA_TYPES_BYTE];
38677 value->arrayLength = str->length;
38678 value->data = str->data;
38679 return;
38680 }
38681
38682 /* An enum was sent as an int32, or an opaque type as a bytestring. This
38683 * is detected with the typeKind indicating the "true" datatype. */
38684 UA_DataTypeKind te1 = typeEquivalence(t: targetDataType);
38685 UA_DataTypeKind te2 = typeEquivalence(t: value->type);
38686 if(te1 == te2 && te1 <= UA_DATATYPEKIND_ENUM) {
38687 value->type = targetDataType;
38688 return;
38689 }
38690
38691 /* No more possible equivalencies */
38692}
38693
38694static UA_StatusCode
38695writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session,
38696 UA_VariableNode *node, const UA_VariableTypeNode *type,
38697 size_t arrayDimensionsSize, UA_UInt32 *arrayDimensions) {
38698 UA_assert(node != NULL);
38699 UA_assert(type != NULL);
38700
38701 /* If this is a variabletype, there must be no instances or subtypes of it
38702 * when we do the change */
38703 if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
38704 UA_Node_hasSubTypeOrInstances(head: &node->head)) {
38705 UA_LOG_INFO(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38706 msg: "Cannot change a variable type with existing instances");
38707 return UA_STATUSCODE_BADINTERNALERROR;
38708 }
38709
38710 /* Check that the array dimensions match with the valuerank */
38711 if(!compatibleValueRankArrayDimensions(server, session, valueRank: node->valueRank,
38712 arrayDimensionsSize)) {
38713 UA_LOG_DEBUG(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38714 msg: "Cannot write the ArrayDimensions. The ValueRank does not match.");
38715 return UA_STATUSCODE_BADTYPEMISMATCH;
38716 }
38717
38718 /* Check if the array dimensions match with the wildcards in the
38719 * variabletype (dimension length 0) */
38720 if(type->arrayDimensions &&
38721 !compatibleArrayDimensions(constraintArrayDimensionsSize: type->arrayDimensionsSize, constraintArrayDimensions: type->arrayDimensions,
38722 testArrayDimensionsSize: arrayDimensionsSize, testArrayDimensions: arrayDimensions)) {
38723 UA_LOG_DEBUG(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38724 msg: "Array dimensions in the variable type do not match");
38725 return UA_STATUSCODE_BADTYPEMISMATCH;
38726 }
38727
38728 /* Check if the current value is compatible with the array dimensions */
38729 UA_DataValue value;
38730 UA_DataValue_init(p: &value);
38731 UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value);
38732 if(retval != UA_STATUSCODE_GOOD)
38733 return retval;
38734 if(value.hasValue) {
38735 if(!compatibleValueArrayDimensions(value: &value.value, targetArrayDimensionsSize: arrayDimensionsSize,
38736 targetArrayDimensions: arrayDimensions))
38737 retval = UA_STATUSCODE_BADTYPEMISMATCH;
38738 UA_DataValue_clear(p: &value);
38739 if(retval != UA_STATUSCODE_GOOD) {
38740 UA_LOG_DEBUG(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38741 msg: "Array dimensions in the current value do not match");
38742 return retval;
38743 }
38744 }
38745
38746 /* Ok, apply */
38747 UA_UInt32 *oldArrayDimensions = node->arrayDimensions;
38748 size_t oldArrayDimensionsSize = node->arrayDimensionsSize;
38749 retval = UA_Array_copy(src: arrayDimensions, size: arrayDimensionsSize,
38750 dst: (void**)&node->arrayDimensions,
38751 type: &UA_TYPES[UA_TYPES_UINT32]);
38752 if(retval != UA_STATUSCODE_GOOD)
38753 return retval;
38754 UA_Array_delete(p: oldArrayDimensions, size: oldArrayDimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]);
38755 node->arrayDimensionsSize = arrayDimensionsSize;
38756 return UA_STATUSCODE_GOOD;
38757}
38758
38759/* Stack layout: ... | node | type */
38760static UA_StatusCode
38761writeValueRankAttribute(UA_Server *server, UA_Session *session,
38762 UA_VariableNode *node, const UA_VariableTypeNode *type,
38763 UA_Int32 valueRank) {
38764 UA_assert(node != NULL);
38765 UA_assert(type != NULL);
38766
38767 UA_Int32 constraintValueRank = type->valueRank;
38768
38769 /* If this is a variabletype, there must be no instances or subtypes of it
38770 * when we do the change */
38771 if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
38772 UA_Node_hasSubTypeOrInstances(head: &node->head))
38773 return UA_STATUSCODE_BADINTERNALERROR;
38774
38775 /* Check if the valuerank of the variabletype allows the change. */
38776 if(!compatibleValueRanks(valueRank, constraintValueRank))
38777 return UA_STATUSCODE_BADTYPEMISMATCH;
38778
38779 /* Check if the new valuerank is compatible with the array dimensions. Use
38780 * the read service to handle data sources. */
38781 size_t arrayDims = node->arrayDimensionsSize;
38782 if(arrayDims == 0) {
38783 /* the value could be an array with no arrayDimensions defined.
38784 dimensions zero indicate a scalar for compatibleValueRankArrayDimensions. */
38785 UA_DataValue value;
38786 UA_DataValue_init(p: &value);
38787 UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value);
38788 if(retval != UA_STATUSCODE_GOOD)
38789 return retval;
38790 if(!value.hasValue || !value.value.type) {
38791 /* no value -> apply */
38792 node->valueRank = valueRank;
38793 return UA_STATUSCODE_GOOD;
38794 }
38795 if(!UA_Variant_isScalar(v: &value.value))
38796 arrayDims = 1;
38797 UA_DataValue_clear(p: &value);
38798 }
38799 if(!compatibleValueRankArrayDimensions(server, session, valueRank, arrayDimensionsSize: arrayDims))
38800 return UA_STATUSCODE_BADTYPEMISMATCH;
38801
38802 /* All good, apply the change */
38803 node->valueRank = valueRank;
38804 return UA_STATUSCODE_GOOD;
38805}
38806
38807static UA_StatusCode
38808writeDataTypeAttribute(UA_Server *server, UA_Session *session,
38809 UA_VariableNode *node, const UA_VariableTypeNode *type,
38810 const UA_NodeId *dataType) {
38811 UA_assert(node != NULL);
38812 UA_assert(type != NULL);
38813
38814 /* If this is a variabletype, there must be no instances or subtypes of it
38815 when we do the change */
38816 if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
38817 UA_Node_hasSubTypeOrInstances(head: &node->head))
38818 return UA_STATUSCODE_BADINTERNALERROR;
38819
38820 /* Does the new type match the constraints of the variabletype? */
38821 if(!compatibleDataTypes(server, dataType, constraintDataType: &type->dataType))
38822 return UA_STATUSCODE_BADTYPEMISMATCH;
38823
38824 /* Check if the current value would match the new type */
38825 UA_DataValue value;
38826 UA_DataValue_init(p: &value);
38827 UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value);
38828 if(retval != UA_STATUSCODE_GOOD)
38829 return retval;
38830 if(value.hasValue) {
38831 const char *reason; /* temp value */
38832 if(!compatibleValue(server, session, targetDataTypeId: dataType, targetValueRank: node->valueRank,
38833 targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions,
38834 value: &value.value, NULL, reason: &reason))
38835 retval = UA_STATUSCODE_BADTYPEMISMATCH;
38836 UA_DataValue_clear(p: &value);
38837 if(retval != UA_STATUSCODE_GOOD) {
38838 UA_LOG_DEBUG(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38839 msg: "The current value does not match the new data type");
38840 return retval;
38841 }
38842 }
38843
38844 /* Replace the datatype nodeid */
38845 UA_NodeId dtCopy = node->dataType;
38846 retval = UA_NodeId_copy(src: dataType, dst: &node->dataType);
38847 if(retval != UA_STATUSCODE_GOOD) {
38848 node->dataType = dtCopy;
38849 return retval;
38850 }
38851 UA_NodeId_clear(p: &dtCopy);
38852 return UA_STATUSCODE_GOOD;
38853}
38854
38855static UA_StatusCode
38856writeValueAttributeWithoutRange(UA_VariableNode *node, const UA_DataValue *value) {
38857 UA_DataValue new_value;
38858 UA_StatusCode retval = UA_DataValue_copy(src: value, dst: &new_value);
38859 if(retval != UA_STATUSCODE_GOOD)
38860 return retval;
38861 UA_DataValue_clear(p: &node->value.data.value);
38862 node->value.data.value = new_value;
38863 return UA_STATUSCODE_GOOD;
38864}
38865
38866static UA_StatusCode
38867writeValueAttributeWithRange(UA_VariableNode *node, const UA_DataValue *value,
38868 const UA_NumericRange *rangeptr) {
38869 /* Value on both sides? */
38870 if(value->status != node->value.data.value.status ||
38871 !value->hasValue || !node->value.data.value.hasValue)
38872 return UA_STATUSCODE_BADINDEXRANGEINVALID;
38873
38874 /* Make scalar a one-entry array for range matching */
38875 UA_Variant editableValue;
38876 const UA_Variant *v = &value->value;
38877 if(UA_Variant_isScalar(v: &value->value)) {
38878 editableValue = value->value;
38879 editableValue.arrayLength = 1;
38880 v = &editableValue;
38881 }
38882
38883 /* Check that the type is an exact match and not only "compatible" */
38884 if(!node->value.data.value.value.type || !v->type ||
38885 !UA_NodeId_equal(n1: &node->value.data.value.value.type->typeId,
38886 n2: &v->type->typeId))
38887 return UA_STATUSCODE_BADTYPEMISMATCH;
38888
38889 /* Write the value */
38890 UA_StatusCode retval =
38891 UA_Variant_setRangeCopy(v: &node->value.data.value.value,
38892 array: v->data, arraySize: v->arrayLength, range: *rangeptr);
38893 if(retval != UA_STATUSCODE_GOOD)
38894 return retval;
38895
38896 /* Write the status and timestamps */
38897 node->value.data.value.hasStatus = value->hasStatus;
38898 node->value.data.value.status = value->status;
38899 node->value.data.value.hasSourceTimestamp = value->hasSourceTimestamp;
38900 node->value.data.value.sourceTimestamp = value->sourceTimestamp;
38901 node->value.data.value.hasSourcePicoseconds = value->hasSourcePicoseconds;
38902 node->value.data.value.sourcePicoseconds = value->sourcePicoseconds;
38903 return UA_STATUSCODE_GOOD;
38904}
38905
38906/* Stack layout: ... | node */
38907static UA_StatusCode
38908writeNodeValueAttribute(UA_Server *server, UA_Session *session,
38909 UA_VariableNode *node, const UA_DataValue *value,
38910 const UA_String *indexRange) {
38911 UA_assert(node != NULL);
38912 UA_assert(session != NULL);
38913
38914 /* Parse the range */
38915 UA_NumericRange range;
38916 range.dimensions = NULL;
38917 UA_NumericRange *rangeptr = NULL;
38918 UA_StatusCode retval = UA_STATUSCODE_GOOD;
38919 if(indexRange && indexRange->length > 0) {
38920 retval = UA_NumericRange_parse(range: &range, str: *indexRange);
38921 if(retval != UA_STATUSCODE_GOOD)
38922 return retval;
38923 rangeptr = &range;
38924 }
38925
38926 /* Created an editable version. The data is not touched. Only the variant
38927 * "container". */
38928 UA_DataValue adjustedValue = *value;
38929
38930 /* Type checking. May change the type of editableValue */
38931 if(value->hasValue && value->value.type) {
38932 adjustValueType(server, value: &adjustedValue.value, targetDataTypeId: &node->dataType);
38933
38934 /* The value may be an extension object, especially the nodeset compiler
38935 * uses extension objects to write variable values. If value is an
38936 * extension object we check if the current node value is also an
38937 * extension object. */
38938 const UA_NodeId nodeDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STRUCTURE);
38939 const UA_NodeId *nodeDataTypePtr = &node->dataType;
38940 if(value->value.type->typeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
38941 value->value.type->typeId.identifier.numeric == UA_NS0ID_STRUCTURE)
38942 nodeDataTypePtr = &nodeDataType;
38943
38944 const char *reason;
38945 if(!compatibleValue(server, session, targetDataTypeId: nodeDataTypePtr, targetValueRank: node->valueRank,
38946 targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions,
38947 value: &adjustedValue.value, range: rangeptr, reason: &reason)) {
38948 UA_LOG_NODEID_WARNING(&node->head.nodeId,
38949 if(session == &server->adminSession) {
38950 /* If the value is written via the local API, log a warning */
38951 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
38952 "Writing the value of Node %.*s failed with the "
38953 "following reason: %s",
38954 (int)nodeIdStr.length, nodeIdStr.data, reason);
38955 } else {
38956 /* Don't spam the logs if writing from remote failed */
38957 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
38958 "Writing the value of Node %.*s failed with the "
38959 "following reason: %s",
38960 (int)nodeIdStr.length, nodeIdStr.data, reason);
38961 });
38962 if(rangeptr && rangeptr->dimensions != NULL)
38963 UA_free(ptr: rangeptr->dimensions);
38964 return UA_STATUSCODE_BADTYPEMISMATCH;
38965 }
38966 }
38967
38968 /* Set the source timestamp if there is none */
38969 UA_DateTime now = UA_DateTime_now();
38970 if(!adjustedValue.hasSourceTimestamp) {
38971 adjustedValue.sourceTimestamp = now;
38972 adjustedValue.hasSourceTimestamp = true;
38973 }
38974
38975 /* Update the timestamp when the value was last updated in the server */
38976 adjustedValue.serverTimestamp = now;
38977 adjustedValue.hasServerTimestamp = true;
38978
38979 switch(node->valueBackend.backendType) {
38980 case UA_VALUEBACKENDTYPE_NONE:
38981 /* Ok, do it */
38982 if(node->valueSource == UA_VALUESOURCE_DATA) {
38983 if(!rangeptr)
38984 retval = writeValueAttributeWithoutRange(node, value: &adjustedValue);
38985 else
38986 retval = writeValueAttributeWithRange(node, value: &adjustedValue, rangeptr);
38987
38988#ifdef UA_ENABLE_HISTORIZING
38989 /* node is a UA_VariableNode*, but it may also point to a
38990 UA_VariableTypeNode */
38991 /* UA_VariableTypeNode doesn't have the historizing attribute */
38992 if(retval == UA_STATUSCODE_GOOD &&
38993 node->head.nodeClass == UA_NODECLASS_VARIABLE &&
38994 server->config.historyDatabase.setValue) {
38995 UA_UNLOCK(&server->serviceMutex);
38996 server->config.historyDatabase.
38997 setValue(server, server->config.historyDatabase.context,
38998 &session->sessionId, session->sessionHandle,
38999 &node->head.nodeId, node->historizing, &adjustedValue);
39000 UA_LOCK(&server->serviceMutex);
39001 }
39002#endif
39003 /* Callback after writing */
39004 if(retval == UA_STATUSCODE_GOOD && node->value.data.callback.onWrite) {
39005 UA_UNLOCK(&server->serviceMutex);
39006 node->value.data.callback.
39007 onWrite(server, &session->sessionId, session->sessionHandle,
39008 &node->head.nodeId, node->head.context,
39009 rangeptr, &adjustedValue);
39010 UA_LOCK(&server->serviceMutex);
39011
39012 }
39013 } else {
39014 if(node->value.dataSource.write) {
39015 UA_UNLOCK(&server->serviceMutex);
39016 retval = node->value.dataSource.
39017 write(server, &session->sessionId, session->sessionHandle,
39018 &node->head.nodeId, node->head.context,
39019 rangeptr, &adjustedValue);
39020 UA_LOCK(&server->serviceMutex);
39021 } else {
39022 retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
39023 }
39024 }
39025 break;
39026 case UA_VALUEBACKENDTYPE_INTERNAL:
39027 break;
39028 case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
39029 break;
39030 case UA_VALUEBACKENDTYPE_EXTERNAL:
39031 if(node->valueBackend.backend.external.callback.userWrite == NULL){
39032 if(rangeptr && rangeptr->dimensions != NULL)
39033 UA_free(ptr: rangeptr->dimensions);
39034 return UA_STATUSCODE_BADWRITENOTSUPPORTED;
39035 }
39036 retval = node->valueBackend.backend.external.callback.
39037 userWrite(server, &session->sessionId, session->sessionHandle,
39038 &node->head.nodeId, node->head.context,
39039 rangeptr, &adjustedValue);
39040 break;
39041 }
39042
39043 /* Clean up */
39044 if(rangeptr && rangeptr->dimensions != NULL)
39045 UA_free(ptr: rangeptr->dimensions);
39046 return retval;
39047}
39048
39049static UA_StatusCode
39050writeIsAbstractAttribute(UA_Node *node, UA_Boolean value) {
39051 switch(node->head.nodeClass) {
39052 case UA_NODECLASS_OBJECTTYPE:
39053 node->objectTypeNode.isAbstract = value;
39054 break;
39055 case UA_NODECLASS_REFERENCETYPE:
39056 node->referenceTypeNode.isAbstract = value;
39057 break;
39058 case UA_NODECLASS_VARIABLETYPE:
39059 node->variableTypeNode.isAbstract = value;
39060 break;
39061 case UA_NODECLASS_DATATYPE:
39062 node->dataTypeNode.isAbstract = value;
39063 break;
39064 default:
39065 return UA_STATUSCODE_BADNODECLASSINVALID;
39066 }
39067 return UA_STATUSCODE_GOOD;
39068}
39069
39070/*****************/
39071/* Write Service */
39072/*****************/
39073
39074#define CHECK_DATATYPE_SCALAR(EXP_DT) \
39075 if(!wvalue->value.hasValue || \
39076 &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type || \
39077 !UA_Variant_isScalar(&wvalue->value.value)) { \
39078 retval = UA_STATUSCODE_BADTYPEMISMATCH; \
39079 break; \
39080 }
39081
39082#define CHECK_DATATYPE_ARRAY(EXP_DT) \
39083 if(!wvalue->value.hasValue || \
39084 &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type || \
39085 UA_Variant_isScalar(&wvalue->value.value)) { \
39086 retval = UA_STATUSCODE_BADTYPEMISMATCH; \
39087 break; \
39088 }
39089
39090#define CHECK_NODECLASS_WRITE(CLASS) \
39091 if((node->head.nodeClass & (CLASS)) == 0) { \
39092 retval = UA_STATUSCODE_BADNODECLASSINVALID; \
39093 break; \
39094 }
39095
39096#define CHECK_USERWRITEMASK(mask) \
39097 if(!(userWriteMask & (mask))) { \
39098 retval = UA_STATUSCODE_BADUSERACCESSDENIED; \
39099 break; \
39100 }
39101
39102#define GET_NODETYPE \
39103 type = (const UA_VariableTypeNode*) \
39104 getNodeType(server, &node->head); \
39105 if(!type) { \
39106 retval = UA_STATUSCODE_BADTYPEMISMATCH; \
39107 break; \
39108 }
39109
39110/* Update a localized text. Don't touch the target if copying fails
39111 * (maybe due to BadOutOfMemory). */
39112static UA_StatusCode
39113updateLocalizedText(const UA_LocalizedText *source, UA_LocalizedText *target) {
39114 UA_LocalizedText tmp;
39115 UA_StatusCode retval = UA_LocalizedText_copy(src: source, dst: &tmp);
39116 if(retval != UA_STATUSCODE_GOOD)
39117 return retval;
39118 UA_LocalizedText_clear(p: target);
39119 *target = tmp;
39120 return UA_STATUSCODE_GOOD;
39121}
39122
39123/* Trigger sampling if a MonitoredItem surveils the attribute with no sampling
39124 * interval */
39125#ifdef UA_ENABLE_SUBSCRIPTIONS
39126static void
39127triggerImmediateDataChange(UA_Server *server, UA_Session *session,
39128 UA_Node *node, const UA_WriteValue *wvalue) {
39129 UA_MonitoredItem *mon = node->head.monitoredItems;
39130 for(; mon != NULL; mon = mon->sampling.nodeListNext) {
39131 if(mon->itemToMonitor.attributeId != wvalue->attributeId)
39132 continue;
39133 UA_DataValue value;
39134 UA_DataValue_init(p: &value);
39135 ReadWithNode(node, server, session, timestampsToReturn: mon->timestampsToReturn,
39136 id: &mon->itemToMonitor, v: &value);
39137 UA_Subscription *sub = mon->subscription;
39138 UA_StatusCode res = sampleCallbackWithValue(server, sub, mon, value: &value);
39139 if(res != UA_STATUSCODE_GOOD) {
39140 UA_DataValue_clear(p: &value);
39141 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
39142 "MonitoredItem %" PRIi32 " | "
39143 "Sampling returned the statuscode %s",
39144 mon->monitoredItemId,
39145 UA_StatusCode_name(res));
39146 }
39147 }
39148}
39149#endif
39150
39151/* This function implements the main part of the write service and operates on a
39152 copy of the node (not in single-threaded mode). */
39153static UA_StatusCode
39154copyAttributeIntoNode(UA_Server *server, UA_Session *session,
39155 UA_Node *node, const UA_WriteValue *wvalue) {
39156 UA_assert(session != NULL);
39157 const void *value = wvalue->value.value.data;
39158 UA_UInt32 userWriteMask = getUserWriteMask(server, session, head: &node->head);
39159 UA_StatusCode retval = UA_STATUSCODE_GOOD;
39160
39161 UA_LOG_NODEID_DEBUG(&node->head.nodeId,
39162 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39163 "Write attribute %"PRIi32 " of Node %.*s",
39164 wvalue->attributeId, (int)nodeIdStr.length,
39165 nodeIdStr.data));
39166
39167 const UA_VariableTypeNode *type;
39168
39169 switch(wvalue->attributeId) {
39170 case UA_ATTRIBUTEID_NODEID:
39171 case UA_ATTRIBUTEID_NODECLASS:
39172 case UA_ATTRIBUTEID_USERWRITEMASK:
39173 case UA_ATTRIBUTEID_USERACCESSLEVEL:
39174 case UA_ATTRIBUTEID_USEREXECUTABLE:
39175 case UA_ATTRIBUTEID_BROWSENAME: /* BrowseName is tracked in a binary tree
39176 for fast lookup */
39177 retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
39178 break;
39179 case UA_ATTRIBUTEID_DISPLAYNAME:
39180 CHECK_USERWRITEMASK(UA_WRITEMASK_DISPLAYNAME);
39181 CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
39182 retval = updateLocalizedText(source: (const UA_LocalizedText *)value,
39183 target: &node->head.displayName);
39184 break;
39185 case UA_ATTRIBUTEID_DESCRIPTION:
39186 CHECK_USERWRITEMASK(UA_WRITEMASK_DESCRIPTION);
39187 CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
39188 retval = updateLocalizedText(source: (const UA_LocalizedText *)value,
39189 target: &node->head.description);
39190 break;
39191 case UA_ATTRIBUTEID_WRITEMASK:
39192 CHECK_USERWRITEMASK(UA_WRITEMASK_WRITEMASK);
39193 CHECK_DATATYPE_SCALAR(UINT32);
39194 node->head.writeMask = *(const UA_UInt32*)value;
39195 break;
39196 case UA_ATTRIBUTEID_ISABSTRACT:
39197 CHECK_USERWRITEMASK(UA_WRITEMASK_ISABSTRACT);
39198 CHECK_DATATYPE_SCALAR(BOOLEAN);
39199 retval = writeIsAbstractAttribute(node, value: *(const UA_Boolean*)value);
39200 break;
39201 case UA_ATTRIBUTEID_SYMMETRIC:
39202 CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
39203 CHECK_USERWRITEMASK(UA_WRITEMASK_SYMMETRIC);
39204 CHECK_DATATYPE_SCALAR(BOOLEAN);
39205 node->referenceTypeNode.symmetric = *(const UA_Boolean*)value;
39206 break;
39207 case UA_ATTRIBUTEID_INVERSENAME:
39208 CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
39209 CHECK_USERWRITEMASK(UA_WRITEMASK_INVERSENAME);
39210 CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
39211 retval = updateLocalizedText(source: (const UA_LocalizedText *)value,
39212 target: &node->referenceTypeNode.inverseName);
39213 break;
39214 case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
39215 CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW);
39216 CHECK_USERWRITEMASK(UA_WRITEMASK_CONTAINSNOLOOPS);
39217 CHECK_DATATYPE_SCALAR(BOOLEAN);
39218 node->viewNode.containsNoLoops = *(const UA_Boolean*)value;
39219 break;
39220 case UA_ATTRIBUTEID_EVENTNOTIFIER:
39221 CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
39222 CHECK_USERWRITEMASK(UA_WRITEMASK_EVENTNOTIFIER);
39223 CHECK_DATATYPE_SCALAR(BYTE);
39224 if(node->head.nodeClass == UA_NODECLASS_VIEW) {
39225 node->viewNode.eventNotifier = *(const UA_Byte*)value;
39226 } else {
39227 node->objectNode.eventNotifier = *(const UA_Byte*)value;
39228 }
39229 break;
39230 case UA_ATTRIBUTEID_VALUE:
39231 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
39232 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
39233 /* The access to a value variable is granted via the AccessLevel
39234 * and UserAccessLevel attributes */
39235 UA_Byte accessLevel = getAccessLevel(server, session, node: &node->variableNode);
39236 if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) {
39237 retval = UA_STATUSCODE_BADNOTWRITABLE;
39238 break;
39239 }
39240 accessLevel = getUserAccessLevel(server, session, node: &node->variableNode);
39241 if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) {
39242 retval = UA_STATUSCODE_BADUSERACCESSDENIED;
39243 break;
39244 }
39245 } else { /* UA_NODECLASS_VARIABLETYPE */
39246 CHECK_USERWRITEMASK(UA_WRITEMASK_VALUEFORVARIABLETYPE);
39247 }
39248 retval = writeNodeValueAttribute(server, session, node: &node->variableNode,
39249 value: &wvalue->value, indexRange: &wvalue->indexRange);
39250 break;
39251 case UA_ATTRIBUTEID_DATATYPE:
39252 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
39253 CHECK_USERWRITEMASK(UA_WRITEMASK_DATATYPE);
39254 CHECK_DATATYPE_SCALAR(NODEID);
39255 GET_NODETYPE;
39256 retval = writeDataTypeAttribute(server, session, node: &node->variableNode,
39257 type, dataType: (const UA_NodeId*)value);
39258 UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
39259 break;
39260 case UA_ATTRIBUTEID_VALUERANK:
39261 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
39262 CHECK_USERWRITEMASK(UA_WRITEMASK_VALUERANK);
39263 CHECK_DATATYPE_SCALAR(INT32);
39264 GET_NODETYPE;
39265 retval = writeValueRankAttribute(server, session, node: &node->variableNode,
39266 type, valueRank: *(const UA_Int32*)value);
39267 UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
39268 break;
39269 case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
39270 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
39271 CHECK_USERWRITEMASK(UA_WRITEMASK_ARRRAYDIMENSIONS);
39272 CHECK_DATATYPE_ARRAY(UINT32);
39273 GET_NODETYPE;
39274 retval = writeArrayDimensionsAttribute(server, session, node: &node->variableNode,
39275 type, arrayDimensionsSize: wvalue->value.value.arrayLength,
39276 arrayDimensions: (UA_UInt32 *)wvalue->value.value.data);
39277 UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
39278 break;
39279 case UA_ATTRIBUTEID_ACCESSLEVEL:
39280 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
39281 CHECK_USERWRITEMASK(UA_WRITEMASK_ACCESSLEVEL);
39282 CHECK_DATATYPE_SCALAR(BYTE);
39283 node->variableNode.accessLevel = *(const UA_Byte*)value;
39284 break;
39285 case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
39286 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
39287 CHECK_USERWRITEMASK(UA_WRITEMASK_MINIMUMSAMPLINGINTERVAL);
39288 CHECK_DATATYPE_SCALAR(DOUBLE);
39289 node->variableNode.minimumSamplingInterval = *(const UA_Double*)value;
39290 break;
39291 case UA_ATTRIBUTEID_HISTORIZING:
39292 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
39293 CHECK_USERWRITEMASK(UA_WRITEMASK_HISTORIZING);
39294 CHECK_DATATYPE_SCALAR(BOOLEAN);
39295 node->variableNode.historizing = *(const UA_Boolean*)value;
39296 break;
39297 case UA_ATTRIBUTEID_EXECUTABLE:
39298 CHECK_NODECLASS_WRITE(UA_NODECLASS_METHOD);
39299 CHECK_USERWRITEMASK(UA_WRITEMASK_EXECUTABLE);
39300 CHECK_DATATYPE_SCALAR(BOOLEAN);
39301 node->methodNode.executable = *(const UA_Boolean*)value;
39302 break;
39303 default:
39304 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
39305 break;
39306 }
39307
39308 /* Check if writing succeeded */
39309 if(retval != UA_STATUSCODE_GOOD) {
39310 UA_LOG_INFO_SESSION(&server->config.logger, session,
39311 "WriteRequest returned status code %s",
39312 UA_StatusCode_name(retval));
39313 return retval;
39314 }
39315
39316 /* Trigger MonitoredItems with no SamplingInterval */
39317#ifdef UA_ENABLE_SUBSCRIPTIONS
39318 triggerImmediateDataChange(server, session, node, wvalue);
39319#endif
39320
39321 return UA_STATUSCODE_GOOD;
39322}
39323
39324static void
39325Operation_Write(UA_Server *server, UA_Session *session, void *context,
39326 const UA_WriteValue *wv, UA_StatusCode *result) {
39327 UA_assert(session != NULL);
39328 *result = UA_Server_editNode(server, session, nodeId: &wv->nodeId,
39329 callback: (UA_EditNodeCallback)copyAttributeIntoNode,
39330 data: (void*)(uintptr_t)wv);
39331}
39332
39333void
39334Service_Write(UA_Server *server, UA_Session *session,
39335 const UA_WriteRequest *request,
39336 UA_WriteResponse *response) {
39337 UA_assert(session != NULL);
39338 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39339 "Processing WriteRequest");
39340 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39341
39342 if(server->config.maxNodesPerWrite != 0 &&
39343 request->nodesToWriteSize > server->config.maxNodesPerWrite) {
39344 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
39345 return;
39346 }
39347
39348 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39349
39350 response->responseHeader.serviceResult =
39351 UA_Server_processServiceOperations(server, session,
39352 operationCallback: (UA_ServiceOperation)Operation_Write, NULL,
39353 requestOperations: &request->nodesToWriteSize,
39354 requestOperationsType: &UA_TYPES[UA_TYPES_WRITEVALUE],
39355 responseOperations: &response->resultsSize,
39356 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
39357}
39358
39359UA_StatusCode
39360UA_Server_write(UA_Server *server, const UA_WriteValue *value) {
39361 UA_StatusCode res = UA_STATUSCODE_GOOD;
39362 UA_LOCK(&server->serviceMutex);
39363 Operation_Write(server, session: &server->adminSession, NULL, wv: value, result: &res);
39364 UA_UNLOCK(&server->serviceMutex);
39365 return res;
39366}
39367
39368/* Convenience function to be wrapped into inline functions */
39369UA_StatusCode
39370__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
39371 const UA_AttributeId attributeId,
39372 const UA_DataType *attr_type, const void *attr) {
39373 UA_LOCK(&server->serviceMutex);
39374 UA_StatusCode res = writeAttribute(server, session: &server->adminSession,
39375 nodeId, attributeId, attr, attr_type);
39376 UA_UNLOCK(&server->serviceMutex);
39377 return res;
39378}
39379
39380/* Internal convenience function */
39381UA_StatusCode
39382writeAttribute(UA_Server *server, UA_Session *session,
39383 const UA_NodeId *nodeId, const UA_AttributeId attributeId,
39384 const void *attr, const UA_DataType *attr_type) {
39385 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39386
39387 UA_WriteValue wvalue;
39388 UA_WriteValue_init(p: &wvalue);
39389 wvalue.nodeId = *nodeId;
39390 wvalue.attributeId = attributeId;
39391 wvalue.value.hasValue = true;
39392 if(attr_type == &UA_TYPES[UA_TYPES_VARIANT]) {
39393 wvalue.value.value = *(const UA_Variant*)attr;
39394 } else if(attr_type == &UA_TYPES[UA_TYPES_DATAVALUE]) {
39395 wvalue.value = *(const UA_DataValue*)attr;
39396 } else {
39397 /* hacked cast. the target WriteValue is used as const anyway */
39398 UA_Variant_setScalar(v: &wvalue.value.value,
39399 p: (void*)(uintptr_t)attr, type: attr_type);
39400 }
39401
39402 UA_StatusCode res = UA_STATUSCODE_GOOD;
39403 Operation_Write(server, session, NULL, wv: &wvalue, result: &res);
39404 return res;
39405}
39406
39407#ifdef UA_ENABLE_HISTORIZING
39408typedef void
39409 (*UA_HistoryDatabase_readFunc)(UA_Server *server, void *hdbContext,
39410 const UA_NodeId *sessionId, void *sessionContext,
39411 const UA_RequestHeader *requestHeader,
39412 const void *historyReadDetails,
39413 UA_TimestampsToReturn timestampsToReturn,
39414 UA_Boolean releaseContinuationPoints,
39415 size_t nodesToReadSize,
39416 const UA_HistoryReadValueId *nodesToRead,
39417 UA_HistoryReadResponse *response,
39418 void * const * const historyData);
39419
39420void
39421Service_HistoryRead(UA_Server *server, UA_Session *session,
39422 const UA_HistoryReadRequest *request,
39423 UA_HistoryReadResponse *response) {
39424 UA_assert(session != NULL);
39425 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39426 if(server->config.historyDatabase.context == NULL) {
39427 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED;
39428 return;
39429 }
39430
39431 if(request->historyReadDetails.encoding != UA_EXTENSIONOBJECT_DECODED) {
39432 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED;
39433 return;
39434 }
39435
39436 const UA_DataType *historyDataType = &UA_TYPES[UA_TYPES_HISTORYDATA];
39437 UA_HistoryDatabase_readFunc readHistory = NULL;
39438 if(request->historyReadDetails.content.decoded.type ==
39439 &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]) {
39440 UA_ReadRawModifiedDetails *details = (UA_ReadRawModifiedDetails*)
39441 request->historyReadDetails.content.decoded.data;
39442 if(!details->isReadModified) {
39443 readHistory = (UA_HistoryDatabase_readFunc)
39444 server->config.historyDatabase.readRaw;
39445 } else {
39446 historyDataType = &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA];
39447 readHistory = (UA_HistoryDatabase_readFunc)
39448 server->config.historyDatabase.readModified;
39449 }
39450 } else if(request->historyReadDetails.content.decoded.type ==
39451 &UA_TYPES[UA_TYPES_READEVENTDETAILS]) {
39452 historyDataType = &UA_TYPES[UA_TYPES_HISTORYEVENT];
39453 readHistory = (UA_HistoryDatabase_readFunc)
39454 server->config.historyDatabase.readEvent;
39455 } else if(request->historyReadDetails.content.decoded.type ==
39456 &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS]) {
39457 readHistory = (UA_HistoryDatabase_readFunc)
39458 server->config.historyDatabase.readProcessed;
39459 } else if(request->historyReadDetails.content.decoded.type ==
39460 &UA_TYPES[UA_TYPES_READATTIMEDETAILS]) {
39461 readHistory = (UA_HistoryDatabase_readFunc)
39462 server->config.historyDatabase.readAtTime;
39463 } else {
39464 /* TODO handle more request->historyReadDetails.content.decoded.type types */
39465 response->responseHeader.serviceResult = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
39466 return;
39467 }
39468
39469 /* Something to do? */
39470 if(request->nodesToReadSize == 0) {
39471 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
39472 return;
39473 }
39474
39475 /* Check if there are too many operations */
39476 if(server->config.maxNodesPerRead != 0 &&
39477 request->nodesToReadSize > server->config.maxNodesPerRead) {
39478 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
39479 return;
39480 }
39481
39482 /* Allocate a temporary array to forward the result pointers to the
39483 * backend */
39484 void **historyData = (void **)
39485 UA_calloc(nmemb: request->nodesToReadSize, size: sizeof(void*));
39486 if(!historyData) {
39487 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39488 return;
39489 }
39490
39491 /* Allocate the results array */
39492 response->results = (UA_HistoryReadResult*)
39493 UA_Array_new(size: request->nodesToReadSize, type: &UA_TYPES[UA_TYPES_HISTORYREADRESULT]);
39494 if(!response->results) {
39495 UA_free(ptr: historyData);
39496 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39497 return;
39498 }
39499 response->resultsSize = request->nodesToReadSize;
39500
39501 for(size_t i = 0; i < response->resultsSize; ++i) {
39502 void * data = UA_new(type: historyDataType);
39503 UA_ExtensionObject_setValue(eo: &response->results[i].historyData,
39504 p: data, type: historyDataType);
39505 historyData[i] = data;
39506 }
39507 UA_UNLOCK(&server->serviceMutex);
39508 readHistory(server, server->config.historyDatabase.context,
39509 &session->sessionId, session->sessionHandle,
39510 &request->requestHeader,
39511 request->historyReadDetails.content.decoded.data,
39512 request->timestampsToReturn,
39513 request->releaseContinuationPoints,
39514 request->nodesToReadSize, request->nodesToRead,
39515 response, historyData);
39516 UA_LOCK(&server->serviceMutex);
39517 UA_free(ptr: historyData);
39518}
39519
39520void
39521Service_HistoryUpdate(UA_Server *server, UA_Session *session,
39522 const UA_HistoryUpdateRequest *request,
39523 UA_HistoryUpdateResponse *response) {
39524 UA_assert(session != NULL);
39525 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39526
39527 response->resultsSize = request->historyUpdateDetailsSize;
39528 response->results = (UA_HistoryUpdateResult*)
39529 UA_Array_new(size: response->resultsSize, type: &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT]);
39530 if(!response->results) {
39531 response->resultsSize = 0;
39532 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39533 return;
39534 }
39535
39536 for(size_t i = 0; i < request->historyUpdateDetailsSize; ++i) {
39537 UA_HistoryUpdateResult_init(p: &response->results[i]);
39538 if(request->historyUpdateDetails[i].encoding != UA_EXTENSIONOBJECT_DECODED) {
39539 response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
39540 continue;
39541 }
39542
39543 const UA_DataType *updateDetailsType =
39544 request->historyUpdateDetails[i].content.decoded.type;
39545 void *updateDetailsData = request->historyUpdateDetails[i].content.decoded.data;
39546
39547 if(updateDetailsType == &UA_TYPES[UA_TYPES_UPDATEDATADETAILS]) {
39548 if(!server->config.historyDatabase.updateData) {
39549 response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
39550 continue;
39551 }
39552 UA_UNLOCK(&server->serviceMutex);
39553 server->config.historyDatabase.
39554 updateData(server, server->config.historyDatabase.context,
39555 &session->sessionId, session->sessionHandle,
39556 &request->requestHeader,
39557 (UA_UpdateDataDetails*)updateDetailsData,
39558 &response->results[i]);
39559 UA_LOCK(&server->serviceMutex);
39560 continue;
39561 }
39562
39563 if(updateDetailsType == &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]) {
39564 if(!server->config.historyDatabase.deleteRawModified) {
39565 response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
39566 continue;
39567 }
39568 UA_UNLOCK(&server->serviceMutex);
39569 server->config.historyDatabase.
39570 deleteRawModified(server, server->config.historyDatabase.context,
39571 &session->sessionId, session->sessionHandle,
39572 &request->requestHeader,
39573 (UA_DeleteRawModifiedDetails*)updateDetailsData,
39574 &response->results[i]);
39575 UA_LOCK(&server->serviceMutex);
39576 continue;
39577 }
39578
39579 response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
39580 }
39581}
39582
39583#endif
39584
39585UA_StatusCode
39586UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
39587 const UA_QualifiedName propertyName,
39588 const UA_Variant value) {
39589 UA_LOCK(&server->serviceMutex);
39590 UA_StatusCode retVal = writeObjectProperty(server, objectId, propertyName, value);
39591 UA_UNLOCK(&server->serviceMutex);
39592 return retVal;
39593}
39594
39595UA_StatusCode
39596writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
39597 const UA_QualifiedName propertyName,
39598 const UA_Variant value) {
39599 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39600 UA_RelativePathElement rpe;
39601 UA_RelativePathElement_init(p: &rpe);
39602 rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
39603 rpe.isInverse = false;
39604 rpe.includeSubtypes = false;
39605 rpe.targetName = propertyName;
39606
39607 UA_BrowsePath bp;
39608 UA_BrowsePath_init(p: &bp);
39609 bp.startingNode = objectId;
39610 bp.relativePath.elementsSize = 1;
39611 bp.relativePath.elements = &rpe;
39612
39613 UA_StatusCode retval;
39614 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp);
39615 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
39616 retval = bpr.statusCode;
39617 UA_BrowsePathResult_clear(p: &bpr);
39618 return retval;
39619 }
39620
39621 retval = writeValueAttribute(server, session: &server->adminSession,
39622 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
39623
39624 UA_BrowsePathResult_clear(p: &bpr);
39625 return retval;
39626}
39627
39628UA_StatusCode UA_EXPORT
39629UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId,
39630 const UA_QualifiedName propertyName,
39631 const void *value, const UA_DataType *type) {
39632 UA_Variant var;
39633 UA_Variant_init(p: &var);
39634 UA_Variant_setScalar(v: &var, p: (void*)(uintptr_t)value, type);
39635 UA_LOCK(&server->serviceMutex);
39636 UA_StatusCode retval = writeObjectProperty(server, objectId, propertyName, value: var);
39637 UA_UNLOCK(&server->serviceMutex);
39638 return retval;
39639}
39640
39641/**** amalgamated original file "/src/server/ua_services_discovery.c" ****/
39642
39643/* This Source Code Form is subject to the terms of the Mozilla Public
39644 * License, v. 2.0. If a copy of the MPL was not distributed with this
39645 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
39646 *
39647 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
39648 * Copyright 2014-2016 (c) Sten Grüner
39649 * Copyright 2014, 2017 (c) Florian Palm
39650 * Copyright 2016 (c) Oleksiy Vasylyev
39651 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
39652 * Copyright 2017 (c) frax2222
39653 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
39654 */
39655
39656
39657#ifdef UA_ENABLE_DISCOVERY
39658
39659
39660static UA_StatusCode
39661setApplicationDescriptionFromRegisteredServer(const UA_FindServersRequest *request,
39662 UA_ApplicationDescription *target,
39663 const UA_RegisteredServer *registeredServer) {
39664 UA_ApplicationDescription_init(target);
39665 UA_StatusCode retval = UA_String_copy(&registeredServer->serverUri, &target->applicationUri);
39666 if(retval != UA_STATUSCODE_GOOD)
39667 return retval;
39668
39669 retval = UA_String_copy(&registeredServer->productUri, &target->productUri);
39670 if(retval != UA_STATUSCODE_GOOD)
39671 return retval;
39672
39673 // if the client requests a specific locale, select the corresponding server name
39674 if(request->localeIdsSize) {
39675 UA_Boolean appNameFound = false;
39676 for(size_t i =0; i<request->localeIdsSize && !appNameFound; i++) {
39677 for(size_t j =0; j<registeredServer->serverNamesSize; j++) {
39678 if(UA_String_equal(&request->localeIds[i], &registeredServer->serverNames[j].locale)) {
39679 retval = UA_LocalizedText_copy(&registeredServer->serverNames[j],
39680 &target->applicationName);
39681 if(retval != UA_STATUSCODE_GOOD)
39682 return retval;
39683 appNameFound = true;
39684 break;
39685 }
39686 }
39687 }
39688
39689 // server does not have the requested local, therefore we can select the
39690 // most suitable one
39691 if(!appNameFound && registeredServer->serverNamesSize) {
39692 retval = UA_LocalizedText_copy(&registeredServer->serverNames[0],
39693 &target->applicationName);
39694 if(retval != UA_STATUSCODE_GOOD)
39695 return retval;
39696 }
39697 } else if(registeredServer->serverNamesSize) {
39698 // just take the first name
39699 retval = UA_LocalizedText_copy(&registeredServer->serverNames[0], &target->applicationName);
39700 if(retval != UA_STATUSCODE_GOOD)
39701 return retval;
39702 }
39703
39704 target->applicationType = registeredServer->serverType;
39705 retval = UA_String_copy(&registeredServer->gatewayServerUri, &target->gatewayServerUri);
39706 if(retval != UA_STATUSCODE_GOOD)
39707 return retval;
39708 // TODO where do we get the discoveryProfileUri for application data?
39709
39710 target->discoveryUrlsSize = registeredServer->discoveryUrlsSize;
39711 if(registeredServer->discoveryUrlsSize) {
39712 size_t duSize = sizeof(UA_String) * registeredServer->discoveryUrlsSize;
39713 target->discoveryUrls = (UA_String *)UA_malloc(duSize);
39714 if(!target->discoveryUrls)
39715 return UA_STATUSCODE_BADOUTOFMEMORY;
39716 for(size_t i = 0; i < registeredServer->discoveryUrlsSize; i++) {
39717 retval = UA_String_copy(&registeredServer->discoveryUrls[i], &target->discoveryUrls[i]);
39718 if(retval != UA_STATUSCODE_GOOD)
39719 return retval;
39720 }
39721 }
39722
39723 return retval;
39724}
39725#endif
39726
39727static UA_StatusCode
39728setApplicationDescriptionFromServer(UA_ApplicationDescription *target, const UA_Server *server) {
39729 /* Copy ApplicationDescription from the config */
39730 UA_StatusCode result = UA_ApplicationDescription_copy(src: &server->config.applicationDescription, dst: target);
39731 if(result != UA_STATUSCODE_GOOD)
39732 return result;
39733
39734 /* Add the discoveryUrls from the networklayers only if discoveryUrl
39735 * not already present and to avoid redundancy */
39736 if(!target->discoveryUrlsSize) {
39737 size_t discSize = sizeof(UA_String) * (target->discoveryUrlsSize + server->config.networkLayersSize);
39738 UA_String* disc = (UA_String *)UA_realloc(ptr: target->discoveryUrls, size: discSize);
39739 if(!disc)
39740 return UA_STATUSCODE_BADOUTOFMEMORY;
39741 size_t existing = target->discoveryUrlsSize;
39742 target->discoveryUrls = disc;
39743 target->discoveryUrlsSize += server->config.networkLayersSize;
39744
39745 for(size_t i = 0; i < server->config.networkLayersSize; i++) {
39746 UA_ServerNetworkLayer* nl = &server->config.networkLayers[i];
39747 UA_String_copy(src: &nl->discoveryUrl, dst: &target->discoveryUrls[existing + i]);
39748 }
39749 }
39750
39751 return UA_STATUSCODE_GOOD;
39752}
39753
39754void Service_FindServers(UA_Server *server, UA_Session *session,
39755 const UA_FindServersRequest *request,
39756 UA_FindServersResponse *response) {
39757 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing FindServersRequest");
39758 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39759
39760 /* Return the server itself? */
39761 UA_Boolean foundSelf = false;
39762 if(request->serverUrisSize) {
39763 for(size_t i = 0; i < request->serverUrisSize; i++) {
39764 if(UA_String_equal(s1: &request->serverUris[i],
39765 s2: &server->config.applicationDescription.applicationUri)) {
39766 foundSelf = true;
39767 break;
39768 }
39769 }
39770 } else {
39771 foundSelf = true;
39772 }
39773
39774#ifndef UA_ENABLE_DISCOVERY
39775 if(!foundSelf)
39776 return;
39777
39778 UA_ApplicationDescription *ad = UA_ApplicationDescription_new();
39779 if(!ad) {
39780 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39781 return;
39782 }
39783
39784 UA_StatusCode retval = setApplicationDescriptionFromServer(target: ad, server);
39785 if(retval != UA_STATUSCODE_GOOD) {
39786 UA_ApplicationDescription_delete(p: ad);
39787 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39788 return;
39789 }
39790
39791 response->servers = ad;
39792 response->serversSize = 1;
39793 return;
39794
39795#else
39796
39797 /* Allocate enough memory, including memory for the "self" response */
39798 size_t maxResults = server->discoveryManager.registeredServersSize + 1;
39799 response->servers = (UA_ApplicationDescription*)UA_Array_new(maxResults, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
39800 if(!response->servers) {
39801 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39802 return;
39803 }
39804
39805 /* Copy into the response. TODO: Evaluate return codes */
39806 size_t pos = 0;
39807 if(foundSelf)
39808 setApplicationDescriptionFromServer(&response->servers[pos++], server);
39809
39810 registeredServer_list_entry* current;
39811 LIST_FOREACH(current, &server->discoveryManager.registeredServers, pointers) {
39812 UA_Boolean usable = (request->serverUrisSize == 0);
39813 if(!usable) {
39814 /* If client only requested a specific set of servers */
39815 for(size_t i = 0; i < request->serverUrisSize; i++) {
39816 if(UA_String_equal(&current->registeredServer.serverUri, &request->serverUris[i])) {
39817 usable = true;
39818 break;
39819 }
39820 }
39821 }
39822
39823 if(usable)
39824 setApplicationDescriptionFromRegisteredServer(request, &response->servers[pos++],
39825 &current->registeredServer);
39826 }
39827
39828 /* Set the final size */
39829 if(pos > 0) {
39830 response->serversSize = pos;
39831 } else {
39832 UA_free(response->servers);
39833 response->servers = NULL;
39834 }
39835#endif
39836}
39837
39838void
39839Service_GetEndpoints(UA_Server *server, UA_Session *session,
39840 const UA_GetEndpointsRequest *request,
39841 UA_GetEndpointsResponse *response) {
39842 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39843
39844 /* If the client expects to see a specific endpointurl, mirror it back. If
39845 * not, clone the endpoints with the discovery url of all networklayers. */
39846 const UA_String *endpointUrl = &request->endpointUrl;
39847 if(endpointUrl->length > 0) {
39848 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39849 "Processing GetEndpointsRequest with endpointUrl "
39850 UA_PRINTF_STRING_FORMAT, UA_PRINTF_STRING_DATA(*endpointUrl));
39851 } else {
39852 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39853 "Processing GetEndpointsRequest with an empty endpointUrl");
39854 }
39855
39856 /* Clone the endpoint for each networklayer? */
39857 size_t clone_times = 1;
39858 UA_Boolean nl_endpointurl = false;
39859 if(endpointUrl->length == 0) {
39860 clone_times = server->config.networkLayersSize;
39861 nl_endpointurl = true;
39862 }
39863
39864 /* Allocate enough memory */
39865 response->endpoints = (UA_EndpointDescription*)
39866 UA_Array_new(size: server->config.endpointsSize * clone_times,
39867 type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
39868 if(!response->endpoints) {
39869 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39870 return;
39871 }
39872
39873 size_t pos = 0;
39874 UA_StatusCode retval = UA_STATUSCODE_GOOD;
39875 for(size_t j = 0; j < server->config.endpointsSize; ++j) {
39876 /* Test if the supported binary profile shall be returned */
39877 UA_Boolean usable = (request->profileUrisSize == 0);
39878 if(!usable) {
39879 for(size_t i = 0; i < request->profileUrisSize; ++i) {
39880 if(!UA_String_equal(s1: &request->profileUris[i],
39881 s2: &server->config.endpoints[j].transportProfileUri))
39882 continue;
39883 usable = true;
39884 break;
39885 }
39886 }
39887 if(!usable)
39888 continue;
39889
39890 /* Copy into the results */
39891 for(size_t i = 0; i < clone_times; ++i) {
39892 retval |= UA_EndpointDescription_copy(src: &server->config.endpoints[j],
39893 dst: &response->endpoints[pos]);
39894 UA_String_clear(p: &response->endpoints[pos].endpointUrl);
39895 UA_Array_delete(p: response->endpoints[pos].server.discoveryUrls,
39896 size: response->endpoints[pos].server.discoveryUrlsSize,
39897 type: &UA_TYPES[UA_TYPES_STRING]);
39898 response->endpoints[pos].server.discoveryUrls = NULL;
39899 response->endpoints[pos].server.discoveryUrlsSize = 0;
39900 if(nl_endpointurl)
39901 endpointUrl = &server->config.networkLayers[i].discoveryUrl;
39902 retval |= UA_String_copy(src: endpointUrl, dst: &response->endpoints[pos].endpointUrl);
39903 retval |= UA_Array_copy(src: endpointUrl, size: 1,
39904 dst: (void**)&response->endpoints[pos].server.discoveryUrls,
39905 type: &UA_TYPES[UA_TYPES_STRING]);
39906 if(retval != UA_STATUSCODE_GOOD)
39907 goto error;
39908 response->endpoints[pos].server.discoveryUrlsSize = 1;
39909 pos++;
39910 }
39911 }
39912
39913 UA_assert(pos <= server->config.endpointsSize * clone_times);
39914 response->endpointsSize = pos;
39915
39916 /* Clean up the memory of there are no usable results */
39917 if(pos > 0)
39918 return;
39919
39920error:
39921 response->responseHeader.serviceResult = retval;
39922 UA_Array_delete(p: response->endpoints, size: response->endpointsSize,
39923 type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
39924 response->endpoints = NULL;
39925 response->endpointsSize = 0;
39926}
39927
39928#ifdef UA_ENABLE_DISCOVERY
39929
39930static void
39931process_RegisterServer(UA_Server *server, UA_Session *session,
39932 const UA_RequestHeader* requestHeader,
39933 const UA_RegisteredServer *requestServer,
39934 const size_t requestDiscoveryConfigurationSize,
39935 const UA_ExtensionObject *requestDiscoveryConfiguration,
39936 UA_ResponseHeader* responseHeader,
39937 size_t *responseConfigurationResultsSize,
39938 UA_StatusCode **responseConfigurationResults,
39939 size_t *responseDiagnosticInfosSize,
39940 UA_DiagnosticInfo *responseDiagnosticInfos) {
39941 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39942
39943 /* Find the server from the request in the registered list */
39944 registeredServer_list_entry* current;
39945 registeredServer_list_entry *registeredServer_entry = NULL;
39946 LIST_FOREACH(current, &server->discoveryManager.registeredServers, pointers) {
39947 if(UA_String_equal(&current->registeredServer.serverUri, &requestServer->serverUri)) {
39948 registeredServer_entry = current;
39949 break;
39950 }
39951 }
39952
39953 UA_MdnsDiscoveryConfiguration *mdnsConfig = NULL;
39954
39955 const UA_String* mdnsServerName = NULL;
39956 if(requestDiscoveryConfigurationSize) {
39957 *responseConfigurationResults =
39958 (UA_StatusCode *)UA_Array_new(requestDiscoveryConfigurationSize,
39959 &UA_TYPES[UA_TYPES_STATUSCODE]);
39960 if(!(*responseConfigurationResults)) {
39961 responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39962 return;
39963 }
39964 *responseConfigurationResultsSize = requestDiscoveryConfigurationSize;
39965
39966 for(size_t i = 0; i < requestDiscoveryConfigurationSize; i++) {
39967 const UA_ExtensionObject *object = &requestDiscoveryConfiguration[i];
39968 if(!mdnsConfig && (object->encoding == UA_EXTENSIONOBJECT_DECODED ||
39969 object->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
39970 (object->content.decoded.type == &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION])) {
39971 mdnsConfig = (UA_MdnsDiscoveryConfiguration *)object->content.decoded.data;
39972 mdnsServerName = &mdnsConfig->mdnsServerName;
39973 (*responseConfigurationResults)[i] = UA_STATUSCODE_GOOD;
39974 } else {
39975 (*responseConfigurationResults)[i] = UA_STATUSCODE_BADNOTSUPPORTED;
39976 }
39977 }
39978 }
39979
39980 if(!mdnsServerName && requestServer->serverNamesSize)
39981 mdnsServerName = &requestServer->serverNames[0].text;
39982
39983 if(!mdnsServerName) {
39984 responseHeader->serviceResult = UA_STATUSCODE_BADSERVERNAMEMISSING;
39985 return;
39986 }
39987
39988 if(requestServer->discoveryUrlsSize == 0) {
39989 responseHeader->serviceResult = UA_STATUSCODE_BADDISCOVERYURLMISSING;
39990 return;
39991 }
39992
39993 if(requestServer->semaphoreFilePath.length) {
39994#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
39995 char* filePath = (char*)
39996 UA_malloc(sizeof(char)*requestServer->semaphoreFilePath.length+1);
39997 if(!filePath) {
39998 UA_LOG_ERROR_SESSION(&server->config.logger, session,
39999 "Cannot allocate memory for semaphore path. Out of memory.");
40000 responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
40001 return;
40002 }
40003 memcpy(filePath, requestServer->semaphoreFilePath.data, requestServer->semaphoreFilePath.length );
40004 filePath[requestServer->semaphoreFilePath.length] = '\0';
40005 if(!UA_fileExists( filePath )) {
40006 responseHeader->serviceResult = UA_STATUSCODE_BADSEMPAHOREFILEMISSING;
40007 UA_free(filePath);
40008 return;
40009 }
40010 UA_free(filePath);
40011#else
40012 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_CLIENT,
40013 "Ignoring semaphore file path. open62541 not compiled "
40014 "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON");
40015#endif
40016 }
40017
40018#ifdef UA_ENABLE_DISCOVERY_MULTICAST
40019 if(server->config.mdnsEnabled) {
40020 for(size_t i = 0; i < requestServer->discoveryUrlsSize; i++) {
40021 /* create TXT if is online and first index, delete TXT if is offline and last index */
40022 UA_Boolean updateTxt = (requestServer->isOnline && i==0) ||
40023 (!requestServer->isOnline && i==requestServer->discoveryUrlsSize);
40024 UA_Server_updateMdnsForDiscoveryUrl(server, mdnsServerName, mdnsConfig,
40025 &requestServer->discoveryUrls[i],
40026 requestServer->isOnline, updateTxt);
40027 }
40028 }
40029#endif
40030
40031 if(!requestServer->isOnline) {
40032 // server is shutting down. Remove it from the registered servers list
40033 if(!registeredServer_entry) {
40034 // server not found, show warning
40035 UA_LOG_WARNING_SESSION(&server->config.logger, session,
40036 "Could not unregister server %.*s. Not registered.",
40037 (int)requestServer->serverUri.length, requestServer->serverUri.data);
40038 responseHeader->serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
40039 return;
40040 }
40041
40042 if(server->discoveryManager.registerServerCallback) {
40043 UA_UNLOCK(&server->serviceMutex);
40044 server->discoveryManager.
40045 registerServerCallback(requestServer,
40046 server->discoveryManager.registerServerCallbackData);
40047 UA_LOCK(&server->serviceMutex);
40048 }
40049
40050 // server found, remove from list
40051 LIST_REMOVE(registeredServer_entry, pointers);
40052 UA_RegisteredServer_clear(&registeredServer_entry->registeredServer);
40053 UA_free(registeredServer_entry);
40054 server->discoveryManager.registeredServersSize--;
40055 responseHeader->serviceResult = UA_STATUSCODE_GOOD;
40056 return;
40057 }
40058
40059 UA_StatusCode retval = UA_STATUSCODE_GOOD;
40060 if(!registeredServer_entry) {
40061 // server not yet registered, register it by adding it to the list
40062 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Registering new server: %.*s",
40063 (int)requestServer->serverUri.length, requestServer->serverUri.data);
40064
40065 registeredServer_entry =
40066 (registeredServer_list_entry *)UA_malloc(sizeof(registeredServer_list_entry));
40067 if(!registeredServer_entry) {
40068 responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
40069 return;
40070 }
40071
40072 LIST_INSERT_HEAD(&server->discoveryManager.registeredServers, registeredServer_entry, pointers);
40073 UA_atomic_addSize(&server->discoveryManager.registeredServersSize, 1);
40074 } else {
40075 UA_RegisteredServer_clear(&registeredServer_entry->registeredServer);
40076 }
40077
40078 // Always call the callback, if it is set.
40079 // Previously we only called it if it was a new register call. It may be the case that this endpoint
40080 // registered before, then crashed, restarts and registeres again. In that case the entry is not deleted
40081 // and the callback would not be called.
40082 if(server->discoveryManager.registerServerCallback) {
40083 UA_UNLOCK(&server->serviceMutex);
40084 server->discoveryManager.
40085 registerServerCallback(requestServer,
40086 server->discoveryManager.registerServerCallbackData);
40087 UA_LOCK(&server->serviceMutex);
40088 }
40089
40090 // copy the data from the request into the list
40091 UA_RegisteredServer_copy(requestServer, &registeredServer_entry->registeredServer);
40092 registeredServer_entry->lastSeen = UA_DateTime_nowMonotonic();
40093 responseHeader->serviceResult = retval;
40094}
40095
40096void Service_RegisterServer(UA_Server *server, UA_Session *session,
40097 const UA_RegisterServerRequest *request,
40098 UA_RegisterServerResponse *response) {
40099 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40100 "Processing RegisterServerRequest");
40101 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40102 process_RegisterServer(server, session, &request->requestHeader, &request->server, 0,
40103 NULL, &response->responseHeader, 0, NULL, 0, NULL);
40104}
40105
40106void Service_RegisterServer2(UA_Server *server, UA_Session *session,
40107 const UA_RegisterServer2Request *request,
40108 UA_RegisterServer2Response *response) {
40109 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40110 "Processing RegisterServer2Request");
40111 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40112 process_RegisterServer(server, session, &request->requestHeader, &request->server,
40113 request->discoveryConfigurationSize, request->discoveryConfiguration,
40114 &response->responseHeader, &response->configurationResultsSize,
40115 &response->configurationResults, &response->diagnosticInfosSize,
40116 response->diagnosticInfos);
40117}
40118
40119/* Cleanup server registration: If the semaphore file path is set, then it just
40120 * checks the existence of the file. When it is deleted, the registration is
40121 * removed. If there is no semaphore file, then the registration will be removed
40122 * if it is older than 60 minutes. */
40123void UA_Discovery_cleanupTimedOut(UA_Server *server, UA_DateTime nowMonotonic) {
40124 UA_DateTime timedOut = nowMonotonic;
40125 // registration is timed out if lastSeen is older than 60 minutes (default
40126 // value, can be modified by user).
40127 if(server->config.discoveryCleanupTimeout)
40128 timedOut -= server->config.discoveryCleanupTimeout * UA_DATETIME_SEC;
40129
40130 registeredServer_list_entry* current, *temp;
40131 LIST_FOREACH_SAFE(current, &server->discoveryManager.registeredServers, pointers, temp) {
40132 UA_Boolean semaphoreDeleted = false;
40133
40134#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
40135 if(current->registeredServer.semaphoreFilePath.length) {
40136 size_t fpSize = sizeof(char)*current->registeredServer.semaphoreFilePath.length+1;
40137 // todo: malloc may fail: return a statuscode
40138 char* filePath = (char *)UA_malloc(fpSize);
40139 if(filePath) {
40140 memcpy(filePath, current->registeredServer.semaphoreFilePath.data,
40141 current->registeredServer.semaphoreFilePath.length );
40142 filePath[current->registeredServer.semaphoreFilePath.length] = '\0';
40143 semaphoreDeleted = UA_fileExists(filePath) == false;
40144 UA_free(filePath);
40145 } else {
40146 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
40147 "Cannot check registration semaphore. Out of memory");
40148 }
40149 }
40150#endif
40151
40152 if(semaphoreDeleted || (server->config.discoveryCleanupTimeout &&
40153 current->lastSeen < timedOut)) {
40154 if(semaphoreDeleted) {
40155 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
40156 "Registration of server with URI %.*s is removed because "
40157 "the semaphore file '%.*s' was deleted.",
40158 (int)current->registeredServer.serverUri.length,
40159 current->registeredServer.serverUri.data,
40160 (int)current->registeredServer.semaphoreFilePath.length,
40161 current->registeredServer.semaphoreFilePath.data);
40162 } else {
40163 // cppcheck-suppress unreadVariable
40164 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
40165 "Registration of server with URI %.*s has timed out and is removed.",
40166 (int)current->registeredServer.serverUri.length,
40167 current->registeredServer.serverUri.data);
40168 }
40169 LIST_REMOVE(current, pointers);
40170 UA_RegisteredServer_clear(&current->registeredServer);
40171 UA_free(current);
40172 server->discoveryManager.registeredServersSize--;
40173 }
40174 }
40175}
40176
40177/* Called by the UA_Server callback. The OPC UA specification says:
40178 *
40179 * > If an error occurs during registration (e.g. the Discovery Server is not running) then the Server
40180 * > must periodically re-attempt registration. The frequency of these attempts should start at 1 second
40181 * > but gradually increase until the registration frequency is the same as what it would be if not
40182 * > errors occurred. The recommended approach would double the period each attempt until reaching the maximum.
40183 *
40184 * We will do so by using the additional data parameter which holds information
40185 * if the next interval is default or if it is a repeated call. */
40186static void
40187periodicServerRegister(UA_Server *server, void *data) {
40188 UA_assert(data != NULL);
40189 UA_LOCK(&server->serviceMutex);
40190
40191 struct PeriodicServerRegisterCallback *cb = (struct PeriodicServerRegisterCallback *)data;
40192
40193 UA_StatusCode retval = UA_Client_connectSecureChannel(cb->client, cb->discovery_server_url);
40194 if (retval == UA_STATUSCODE_GOOD) {
40195 /* Register
40196 You can also use a semaphore file. That file must exist. When the file is
40197 deleted, the server is automatically unregistered. The semaphore file has
40198 to be accessible by the discovery server
40199
40200 UA_StatusCode retval = UA_Server_register_discovery(server,
40201 "opc.tcp://localhost:4840", "/path/to/some/file");
40202 */
40203 retval = register_server_with_discovery_server(server, cb->client, false, NULL);
40204 if (retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
40205 /* If the periodic interval is higher than the maximum lifetime of
40206 * the session, the server will close the connection. In this case
40207 * we should try to reconnect */
40208 UA_Client_disconnect(cb->client);
40209 retval = UA_Client_connectSecureChannel(cb->client, cb->discovery_server_url);
40210 if (retval == UA_STATUSCODE_GOOD) {
40211 retval = register_server_with_discovery_server(server, cb->client, false, NULL);
40212 }
40213 }
40214 }
40215 /* Registering failed */
40216 if(retval != UA_STATUSCODE_GOOD) {
40217 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
40218 "Could not register server with discovery server. "
40219 "Is the discovery server started? StatusCode %s",
40220 UA_StatusCode_name(retval));
40221
40222 /* If the server was previously registered, retry in one second,
40223 * else, double the previous interval */
40224 UA_Double nextInterval = 1000.0;
40225 if(!cb->registered)
40226 nextInterval = cb->this_interval * 2;
40227
40228 /* The interval should be smaller than the default interval */
40229 if(nextInterval > cb->default_interval)
40230 nextInterval = cb->default_interval;
40231
40232 cb->this_interval = nextInterval;
40233 changeRepeatedCallbackInterval(server, cb->id, nextInterval);
40234 UA_UNLOCK(&server->serviceMutex);
40235 return;
40236 }
40237
40238 /* Registering succeeded */
40239 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
40240 "Server successfully registered. Next periodical register will be in %d seconds",
40241 (int)(cb->default_interval/1000));
40242
40243 if(!cb->registered) {
40244 retval = changeRepeatedCallbackInterval(server, cb->id, cb->default_interval);
40245 /* If changing the interval fails, try again after the next registering */
40246 if(retval == UA_STATUSCODE_GOOD)
40247 cb->registered = true;
40248 }
40249 UA_UNLOCK(&server->serviceMutex);
40250}
40251
40252UA_StatusCode
40253UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
40254 struct UA_Client *client,
40255 const char* discoveryServerUrl,
40256 UA_Double intervalMs,
40257 UA_Double delayFirstRegisterMs,
40258 UA_UInt64 *periodicCallbackId) {
40259 UA_LOCK(&server->serviceMutex);
40260 /* No valid server URL */
40261 if(!discoveryServerUrl) {
40262 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
40263 "No discovery server URL provided");
40264 UA_UNLOCK(&server->serviceMutex);
40265 return UA_STATUSCODE_BADINTERNALERROR;
40266 }
40267
40268
40269 if (client->connection.state != UA_CONNECTIONSTATE_CLOSED) {
40270 UA_UNLOCK(&server->serviceMutex);
40271 return UA_STATUSCODE_BADINVALIDSTATE;
40272 }
40273
40274 /* Check if we are already registering with the given discovery url and
40275 * remove the old periodic call */
40276 periodicServerRegisterCallback_entry *rs, *rs_tmp;
40277 LIST_FOREACH_SAFE(rs, &server->discoveryManager.
40278 periodicServerRegisterCallbacks, pointers, rs_tmp) {
40279 if(strcmp(rs->callback->discovery_server_url, discoveryServerUrl) == 0) {
40280 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
40281 "There is already a register callback for '%s' in place. "
40282 "Removing the older one.", discoveryServerUrl);
40283 removeCallback(server, rs->callback->id);
40284 LIST_REMOVE(rs, pointers);
40285 UA_free(rs->callback->discovery_server_url);
40286 UA_free(rs->callback);
40287 UA_free(rs);
40288 break;
40289 }
40290 }
40291
40292 /* Allocate and initialize */
40293 struct PeriodicServerRegisterCallback* cb = (struct PeriodicServerRegisterCallback*)
40294 UA_malloc(sizeof(struct PeriodicServerRegisterCallback));
40295 if(!cb) {
40296 UA_UNLOCK(&server->serviceMutex);
40297 return UA_STATUSCODE_BADOUTOFMEMORY;
40298 }
40299
40300 /* Start repeating a failed register after 1s, then increase the delay. Set
40301 * to 500ms, as the delay is doubled before changing the callback
40302 * interval.*/
40303 cb->this_interval = 500.0;
40304 cb->default_interval = intervalMs;
40305 cb->registered = false;
40306 cb->client = client;
40307 size_t len = strlen(discoveryServerUrl);
40308 cb->discovery_server_url = (char*)UA_malloc(len+1);
40309 if (!cb->discovery_server_url) {
40310 UA_free(cb);
40311 UA_UNLOCK(&server->serviceMutex);
40312 return UA_STATUSCODE_BADOUTOFMEMORY;
40313 }
40314 memcpy(cb->discovery_server_url, discoveryServerUrl, len+1);
40315
40316 /* Add the callback */
40317 UA_StatusCode retval =
40318 addRepeatedCallback(server, periodicServerRegister,
40319 cb, delayFirstRegisterMs, &cb->id);
40320 if(retval != UA_STATUSCODE_GOOD) {
40321 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
40322 "Could not create periodic job for server register. "
40323 "StatusCode %s", UA_StatusCode_name(retval));
40324 UA_free(cb);
40325 UA_UNLOCK(&server->serviceMutex);
40326 return retval;
40327 }
40328
40329#ifndef __clang_analyzer__
40330 // the analyzer reports on LIST_INSERT_HEAD a use after free false positive
40331 periodicServerRegisterCallback_entry *newEntry = (periodicServerRegisterCallback_entry*)
40332 UA_malloc(sizeof(periodicServerRegisterCallback_entry));
40333 if(!newEntry) {
40334 removeCallback(server, cb->id);
40335 UA_free(cb);
40336 UA_UNLOCK(&server->serviceMutex);
40337 return UA_STATUSCODE_BADOUTOFMEMORY;
40338 }
40339 newEntry->callback = cb;
40340 LIST_INSERT_HEAD(&server->discoveryManager.periodicServerRegisterCallbacks, newEntry, pointers);
40341#endif
40342
40343 if(periodicCallbackId)
40344 *periodicCallbackId = cb->id;
40345 UA_UNLOCK(&server->serviceMutex);
40346 return UA_STATUSCODE_GOOD;
40347}
40348
40349void
40350UA_Server_setRegisterServerCallback(UA_Server *server,
40351 UA_Server_registerServerCallback cb,
40352 void* data) {
40353 UA_LOCK(&server->serviceMutex);
40354 server->discoveryManager.registerServerCallback = cb;
40355 server->discoveryManager.registerServerCallbackData = data;
40356 UA_UNLOCK(&server->serviceMutex);
40357}
40358
40359#endif /* UA_ENABLE_DISCOVERY */
40360
40361/**** amalgamated original file "/src/server/ua_services_subscription.c" ****/
40362
40363/* This Source Code Form is subject to the terms of the Mozilla Public
40364 * License, v. 2.0. If a copy of the MPL was not distributed with this
40365 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
40366 *
40367 * Copyright 2014-2018, 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
40368 * Copyright 2016-2017 (c) Florian Palm
40369 * Copyright 2015 (c) Chris Iatrou
40370 * Copyright 2015-2016 (c) Sten Grüner
40371 * Copyright 2015-2016 (c) Oleksiy Vasylyev
40372 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
40373 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
40374 * Copyright 2017 (c) Mattias Bornhager
40375 * Copyright 2017 (c) Henrik Norrman
40376 * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
40377 * Copyright 2018 (c) Fabian Arndt, Root-Core
40378 * Copyright 2017-2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
40379 */
40380
40381
40382#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
40383
40384static void
40385setPublishingEnabled(UA_Subscription *sub, UA_Boolean publishingEnabled) {
40386 if(sub->publishingEnabled == publishingEnabled)
40387 return;
40388
40389 sub->publishingEnabled = publishingEnabled;
40390
40391#ifdef UA_ENABLE_DIAGNOSTICS
40392 if(publishingEnabled)
40393 sub->enableCount++;
40394 else
40395 sub->disableCount++;
40396#endif
40397}
40398
40399static void
40400setSubscriptionSettings(UA_Server *server, UA_Subscription *subscription,
40401 UA_Double requestedPublishingInterval,
40402 UA_UInt32 requestedLifetimeCount,
40403 UA_UInt32 requestedMaxKeepAliveCount,
40404 UA_UInt32 maxNotificationsPerPublish,
40405 UA_Byte priority) {
40406 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40407
40408 /* re-parameterize the subscription */
40409 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.publishingIntervalLimits,
40410 requestedPublishingInterval,
40411 subscription->publishingInterval);
40412 /* check for nan*/
40413 if(requestedPublishingInterval != requestedPublishingInterval)
40414 subscription->publishingInterval = server->config.publishingIntervalLimits.min;
40415 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.keepAliveCountLimits,
40416 requestedMaxKeepAliveCount, subscription->maxKeepAliveCount);
40417 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.lifeTimeCountLimits,
40418 requestedLifetimeCount, subscription->lifeTimeCount);
40419 if(subscription->lifeTimeCount < 3 * subscription->maxKeepAliveCount)
40420 subscription->lifeTimeCount = 3 * subscription->maxKeepAliveCount;
40421 subscription->notificationsPerPublish = maxNotificationsPerPublish;
40422 if(maxNotificationsPerPublish == 0 ||
40423 maxNotificationsPerPublish > server->config.maxNotificationsPerPublish)
40424 subscription->notificationsPerPublish = server->config.maxNotificationsPerPublish;
40425 subscription->priority = priority;
40426}
40427
40428void
40429Service_CreateSubscription(UA_Server *server, UA_Session *session,
40430 const UA_CreateSubscriptionRequest *request,
40431 UA_CreateSubscriptionResponse *response) {
40432 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40433
40434 /* Check limits for the number of subscriptions */
40435 if(((server->config.maxSubscriptions != 0) &&
40436 (server->subscriptionsSize >= server->config.maxSubscriptions)) ||
40437 ((server->config.maxSubscriptionsPerSession != 0) &&
40438 (session->subscriptionsSize >= server->config.maxSubscriptionsPerSession))) {
40439 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
40440 return;
40441 }
40442
40443 /* Create the subscription */
40444 UA_Subscription *sub= UA_Subscription_new();
40445 if(!sub) {
40446 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40447 "Processing CreateSubscriptionRequest failed");
40448 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
40449 return;
40450 }
40451
40452 /* Set the subscription parameters */
40453 setSubscriptionSettings(server, subscription: sub, requestedPublishingInterval: request->requestedPublishingInterval,
40454 requestedLifetimeCount: request->requestedLifetimeCount,
40455 requestedMaxKeepAliveCount: request->requestedMaxKeepAliveCount,
40456 maxNotificationsPerPublish: request->maxNotificationsPerPublish, priority: request->priority);
40457 setPublishingEnabled(sub, publishingEnabled: request->publishingEnabled);
40458 sub->currentKeepAliveCount = sub->maxKeepAliveCount; /* set settings first */
40459
40460 /* Assign the SubscriptionId */
40461 sub->subscriptionId = ++server->lastSubscriptionId;
40462
40463 /* Register the cyclic callback */
40464 UA_StatusCode retval = Subscription_registerPublishCallback(server, sub);
40465 if(retval != UA_STATUSCODE_GOOD) {
40466 UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
40467 "Subscription %" PRIu32 " | "
40468 "Could not register publish callback with error code %s",
40469 sub->subscriptionId, UA_StatusCode_name(retval));
40470 response->responseHeader.serviceResult = retval;
40471 UA_Subscription_delete(server, sub);
40472 return;
40473 }
40474
40475 /* Register the subscription in the server */
40476 LIST_INSERT_HEAD(&server->subscriptions, sub, serverListEntry);
40477 server->subscriptionsSize++;
40478
40479 /* Update the server statistics */
40480 server->serverDiagnosticsSummary.currentSubscriptionCount++;
40481 server->serverDiagnosticsSummary.cumulatedSubscriptionCount++;
40482
40483 /* Attach the Subscription to the session */
40484 UA_Session_attachSubscription(session, sub);
40485
40486 /* Prepare the response */
40487 response->subscriptionId = sub->subscriptionId;
40488 response->revisedPublishingInterval = sub->publishingInterval;
40489 response->revisedLifetimeCount = sub->lifeTimeCount;
40490 response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount;
40491
40492#ifdef UA_ENABLE_DIAGNOSTICS
40493 createSubscriptionObject(server, session, sub);
40494#endif
40495
40496 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
40497 "Subscription created (Publishing interval %.2fms, "
40498 "max %lu notifications per publish)",
40499 sub->publishingInterval,
40500 (long unsigned)sub->notificationsPerPublish);}
40501
40502void
40503Service_ModifySubscription(UA_Server *server, UA_Session *session,
40504 const UA_ModifySubscriptionRequest *request,
40505 UA_ModifySubscriptionResponse *response) {
40506 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40507 "Processing ModifySubscriptionRequest");
40508 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40509
40510 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
40511 if(!sub) {
40512 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40513 return;
40514 }
40515
40516 /* Store the old publishing interval */
40517 UA_Double oldPublishingInterval = sub->publishingInterval;
40518 UA_Byte oldPriority = sub->priority;
40519
40520 /* Change the Subscription settings */
40521 setSubscriptionSettings(server, subscription: sub, requestedPublishingInterval: request->requestedPublishingInterval,
40522 requestedLifetimeCount: request->requestedLifetimeCount,
40523 requestedMaxKeepAliveCount: request->requestedMaxKeepAliveCount,
40524 maxNotificationsPerPublish: request->maxNotificationsPerPublish, priority: request->priority);
40525
40526 /* Reset the subscription lifetime */
40527 sub->currentLifetimeCount = 0;
40528
40529 /* Change the repeated callback to the new interval. This cannot fail as the
40530 * CallbackId must exist. */
40531 if(sub->publishCallbackId > 0 &&
40532 sub->publishingInterval != oldPublishingInterval)
40533 changeRepeatedCallbackInterval(server, callbackId: sub->publishCallbackId,
40534 interval_ms: sub->publishingInterval);
40535
40536 /* If the priority has changed, re-enter the subscription to the
40537 * priority-ordered queue in the session. */
40538 if(oldPriority != sub->priority) {
40539 UA_Session_detachSubscription(server, session, sub, false);
40540 UA_Session_attachSubscription(session, sub);
40541 }
40542
40543 /* Set the response */
40544 response->revisedPublishingInterval = sub->publishingInterval;
40545 response->revisedLifetimeCount = sub->lifeTimeCount;
40546 response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount;
40547
40548 /* Update the diagnostics statistics */
40549#ifdef UA_ENABLE_DIAGNOSTICS
40550 sub->modifyCount++;
40551#endif
40552}
40553
40554static void
40555Operation_SetPublishingMode(UA_Server *server, UA_Session *session,
40556 const UA_Boolean *publishingEnabled,
40557 const UA_UInt32 *subscriptionId,
40558 UA_StatusCode *result) {
40559 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40560 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: *subscriptionId);
40561 if(!sub) {
40562 *result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40563 return;
40564 }
40565
40566 sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
40567 setPublishingEnabled(sub, publishingEnabled: *publishingEnabled); /* Set the publishing mode */
40568}
40569
40570void
40571Service_SetPublishingMode(UA_Server *server, UA_Session *session,
40572 const UA_SetPublishingModeRequest *request,
40573 UA_SetPublishingModeResponse *response) {
40574 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40575 "Processing SetPublishingModeRequest");
40576 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40577
40578 UA_Boolean publishingEnabled = request->publishingEnabled; /* request is const */
40579 response->responseHeader.serviceResult =
40580 UA_Server_processServiceOperations(server, session,
40581 operationCallback: (UA_ServiceOperation)Operation_SetPublishingMode,
40582 context: &publishingEnabled,
40583 requestOperations: &request->subscriptionIdsSize,
40584 requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
40585 responseOperations: &response->resultsSize,
40586 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
40587}
40588
40589UA_StatusCode
40590Service_Publish(UA_Server *server, UA_Session *session,
40591 const UA_PublishRequest *request, UA_UInt32 requestId) {
40592 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing PublishRequest");
40593 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40594
40595 /* Return an error if the session has no subscription */
40596 if(TAILQ_EMPTY(&session->subscriptions)) {
40597 sendServiceFault(channel: session->header.channel, requestId,
40598 requestHandle: request->requestHeader.requestHandle,
40599 UA_STATUSCODE_BADNOSUBSCRIPTION);
40600 return UA_STATUSCODE_BADNOSUBSCRIPTION;
40601 }
40602
40603 /* Handle too many subscriptions to free resources before trying to allocate
40604 * resources for the new publish request. If the limit has been reached the
40605 * oldest publish request shall be responded */
40606 if((server->config.maxPublishReqPerSession != 0) &&
40607 (session->responseQueueSize >= server->config.maxPublishReqPerSession)) {
40608 if(!UA_Session_reachedPublishReqLimit(server, session)) {
40609 sendServiceFault(channel: session->header.channel, requestId,
40610 requestHandle: request->requestHeader.requestHandle,
40611 UA_STATUSCODE_BADINTERNALERROR);
40612 return UA_STATUSCODE_BADINTERNALERROR;
40613 }
40614 }
40615
40616 /* Allocate the response to store it in the retransmission queue */
40617 UA_PublishResponseEntry *entry = (UA_PublishResponseEntry *)
40618 UA_malloc(size: sizeof(UA_PublishResponseEntry));
40619 if(!entry) {
40620 sendServiceFault(channel: session->header.channel, requestId,
40621 requestHandle: request->requestHeader.requestHandle,
40622 UA_STATUSCODE_BADOUTOFMEMORY);
40623 return UA_STATUSCODE_BADOUTOFMEMORY;
40624 }
40625
40626 /* Prepare the response */
40627 entry->requestId = requestId;
40628 UA_PublishResponse *response = &entry->response;
40629 UA_PublishResponse_init(p: response);
40630 response->responseHeader.requestHandle = request->requestHeader.requestHandle;
40631
40632 /* Allocate the results array to acknowledge the acknowledge */
40633 if(request->subscriptionAcknowledgementsSize > 0) {
40634 response->results = (UA_StatusCode *)
40635 UA_Array_new(size: request->subscriptionAcknowledgementsSize,
40636 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
40637 if(!response->results) {
40638 UA_free(ptr: entry);
40639 sendServiceFault(channel: session->header.channel, requestId,
40640 requestHandle: request->requestHeader.requestHandle,
40641 UA_STATUSCODE_BADOUTOFMEMORY);
40642 return UA_STATUSCODE_BADOUTOFMEMORY;
40643 }
40644 response->resultsSize = request->subscriptionAcknowledgementsSize;
40645 }
40646
40647 /* <--- A good StatusCode is returned from here on ---> */
40648
40649 /* Delete Acknowledged Subscription Messages */
40650 for(size_t i = 0; i < request->subscriptionAcknowledgementsSize; ++i) {
40651 UA_SubscriptionAcknowledgement *ack = &request->subscriptionAcknowledgements[i];
40652 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: ack->subscriptionId);
40653 if(!sub) {
40654 response->results[i] = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40655 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40656 "Cannot process acknowledgements subscription %u" PRIu32,
40657 ack->subscriptionId);
40658 continue;
40659 }
40660 /* Remove the acked transmission from the retransmission queue */
40661 response->results[i] =
40662 UA_Subscription_removeRetransmissionMessage(sub, sequenceNumber: ack->sequenceNumber);
40663 }
40664
40665 /* Queue the publish response. It will be dequeued in a repeated publish
40666 * callback. This can also be triggered right now for a late
40667 * subscription. */
40668 UA_Session_queuePublishReq(session, entry, false);
40669 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Queued a publication message");
40670
40671 /* If we still had publish requests in the queue, none of the subscriptions
40672 * is late. So we don't have to search for one. */
40673 if(session->responseQueueSize > 1) {
40674 return UA_STATUSCODE_GOOD;
40675 }
40676
40677 /* If there are late subscriptions, the new publish request is used to
40678 * answer them immediately. Late subscriptions with higher priority are
40679 * considered earlier. However, a single subscription that generates many
40680 * notifications must not "starve" other late subscriptions. Hence we move
40681 * it to the end of the queue for the subscriptions of that priority. */
40682 UA_Subscription *late, *late_tmp;
40683 TAILQ_FOREACH_SAFE(late, &session->subscriptions, sessionListEntry, late_tmp) {
40684 if(late->state != UA_SUBSCRIPTIONSTATE_LATE)
40685 continue;
40686
40687 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, late,
40688 "Send PublishResponse on a late subscription");
40689 UA_Subscription_publishOnce(server, sub: late);
40690
40691 /* Skip re-insert if the subscription was deleted during publishOnce */
40692 if(late->session) {
40693 /* Find the first element with smaller priority and insert before
40694 * that. If there is none, insert at the end of the queue. */
40695 UA_Subscription *after = TAILQ_NEXT(late, sessionListEntry);
40696 while(after && after->priority >= late->priority)
40697 after = TAILQ_NEXT(after, sessionListEntry);
40698 TAILQ_REMOVE(&session->subscriptions, late, sessionListEntry);
40699 if(after)
40700 TAILQ_INSERT_BEFORE(after, late, sessionListEntry);
40701 else
40702 TAILQ_INSERT_TAIL(&session->subscriptions, late, sessionListEntry);
40703 }
40704
40705 /* In case of an error we might not have used the publish request that
40706 * was just enqueued. Continue to find late subscriptions in that
40707 * case. */
40708 if(session->responseQueueSize == 0)
40709 break;
40710 }
40711
40712 return UA_STATUSCODE_GOOD;
40713}
40714
40715static void
40716Operation_DeleteSubscription(UA_Server *server, UA_Session *session, void *_,
40717 const UA_UInt32 *subscriptionId, UA_StatusCode *result) {
40718 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: *subscriptionId);
40719 if(!sub) {
40720 *result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40721 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40722 "Deleting Subscription with Id %" PRIu32
40723 " failed with error code %s",
40724 *subscriptionId, UA_StatusCode_name(*result));
40725 return;
40726 }
40727
40728 UA_Subscription_delete(server, sub);
40729 *result = UA_STATUSCODE_GOOD;
40730 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40731 "Subscription %" PRIu32 " | Subscription deleted",
40732 *subscriptionId);
40733}
40734
40735void
40736Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
40737 const UA_DeleteSubscriptionsRequest *request,
40738 UA_DeleteSubscriptionsResponse *response) {
40739 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40740 "Processing DeleteSubscriptionsRequest");
40741 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40742
40743 response->responseHeader.serviceResult =
40744 UA_Server_processServiceOperations(server, session,
40745 operationCallback: (UA_ServiceOperation)Operation_DeleteSubscription, NULL,
40746 requestOperations: &request->subscriptionIdsSize, requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
40747 responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
40748}
40749
40750void
40751Service_Republish(UA_Server *server, UA_Session *session,
40752 const UA_RepublishRequest *request,
40753 UA_RepublishResponse *response) {
40754 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40755 "Processing RepublishRequest");
40756 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40757
40758 /* Get the subscription */
40759 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
40760 if(!sub) {
40761 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40762 return;
40763 }
40764
40765 /* Reset the subscription lifetime */
40766 sub->currentLifetimeCount = 0;
40767
40768 /* Update the subscription statistics */
40769#ifdef UA_ENABLE_DIAGNOSTICS
40770 sub->republishRequestCount++;
40771#endif
40772
40773 /* Find the notification in the retransmission queue */
40774 UA_NotificationMessageEntry *entry;
40775 TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
40776 if(entry->message.sequenceNumber == request->retransmitSequenceNumber)
40777 break;
40778 }
40779 if(!entry) {
40780 response->responseHeader.serviceResult = UA_STATUSCODE_BADMESSAGENOTAVAILABLE;
40781 return;
40782 }
40783
40784 response->responseHeader.serviceResult =
40785 UA_NotificationMessage_copy(src: &entry->message, dst: &response->notificationMessage);
40786
40787 /* Update the subscription statistics for the case where we return a message */
40788#ifdef UA_ENABLE_DIAGNOSTICS
40789 sub->republishMessageCount++;
40790#endif
40791}
40792
40793static UA_StatusCode
40794setTransferredSequenceNumbers(const UA_Subscription *sub, UA_TransferResult *result) {
40795 /* Allocate memory */
40796 result->availableSequenceNumbers = (UA_UInt32*)
40797 UA_Array_new(size: sub->retransmissionQueueSize, type: &UA_TYPES[UA_TYPES_UINT32]);
40798 if(!result->availableSequenceNumbers)
40799 return UA_STATUSCODE_BADOUTOFMEMORY;
40800 result->availableSequenceNumbersSize = sub->retransmissionQueueSize;
40801
40802 /* Copy over the sequence numbers */
40803 UA_NotificationMessageEntry *entry;
40804 size_t i = 0;
40805 TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
40806 result->availableSequenceNumbers[i] = entry->message.sequenceNumber;
40807 i++;
40808 }
40809
40810 UA_assert(i == result->availableSequenceNumbersSize);
40811
40812 return UA_STATUSCODE_GOOD;
40813}
40814
40815static void
40816Operation_TransferSubscription(UA_Server *server, UA_Session *session,
40817 const UA_Boolean *sendInitialValues,
40818 const UA_UInt32 *subscriptionId,
40819 UA_TransferResult *result) {
40820 /* Get the subscription. This requires a server-wide lookup instead of the
40821 * usual session-wide lookup. */
40822 UA_Subscription *sub = UA_Server_getSubscriptionById(server, subscriptionId: *subscriptionId);
40823 if(!sub) {
40824 result->statusCode = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40825 return;
40826 }
40827
40828 /* Update the diagnostics statistics */
40829#ifdef UA_ENABLE_DIAGNOSTICS
40830 sub->transferRequestCount++;
40831#endif
40832
40833 /* Is this the same session? Return the sequence numbers and do nothing else. */
40834 UA_Session *oldSession = sub->session;
40835 if(oldSession == session) {
40836 result->statusCode = setTransferredSequenceNumbers(sub, result);
40837#ifdef UA_ENABLE_DIAGNOSTICS
40838 sub->transferredToSameClientCount++;
40839#endif
40840 return;
40841 }
40842
40843 /* Check with AccessControl if the transfer is allowed */
40844 if(!server->config.accessControl.allowTransferSubscription ||
40845 !server->config.accessControl.
40846 allowTransferSubscription(server, &server->config.accessControl,
40847 oldSession ? &oldSession->sessionId : NULL,
40848 oldSession ? oldSession->sessionHandle : NULL,
40849 &session->sessionId, session->sessionHandle)) {
40850 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
40851 return;
40852 }
40853
40854 /* Check limits for the number of subscriptions for this Session */
40855 if((server->config.maxSubscriptionsPerSession != 0) &&
40856 (session->subscriptionsSize >= server->config.maxSubscriptionsPerSession)) {
40857 result->statusCode = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
40858 return;
40859 }
40860
40861 /* Allocate memory for the new subscription */
40862 UA_Subscription *newSub = (UA_Subscription*)UA_malloc(size: sizeof(UA_Subscription));
40863 if(!newSub) {
40864 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
40865 return;
40866 }
40867
40868 /* Set the available sequence numbers */
40869 result->statusCode = setTransferredSequenceNumbers(sub, result);
40870 if(result->statusCode != UA_STATUSCODE_GOOD) {
40871 UA_free(ptr: newSub);
40872 return;
40873 }
40874
40875 /* Create an identical copy of the Subscription struct. The original
40876 * subscription remains in place until a StatusChange notification has been
40877 * sent. The elements for lists and queues are moved over manually to ensure
40878 * that all backpointers are set correctly. */
40879 memcpy(dest: newSub, src: sub, n: sizeof(UA_Subscription));
40880
40881 /* Register cyclic publish callback */
40882 result->statusCode = Subscription_registerPublishCallback(server, sub: newSub);
40883 if(result->statusCode != UA_STATUSCODE_GOOD) {
40884 UA_Array_delete(p: result->availableSequenceNumbers,
40885 size: sub->retransmissionQueueSize, type: &UA_TYPES[UA_TYPES_UINT32]);
40886 result->availableSequenceNumbers = NULL;
40887 result->availableSequenceNumbersSize = 0;
40888 UA_free(ptr: newSub);
40889 return;
40890 }
40891
40892 /* <-- The point of no return --> */
40893
40894 /* Move over the MonitoredItems and adjust the backpointers */
40895 LIST_INIT(&newSub->monitoredItems);
40896 UA_MonitoredItem *mon, *mon_tmp;
40897 LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, mon_tmp) {
40898 LIST_REMOVE(mon, listEntry);
40899 mon->subscription = newSub;
40900 LIST_INSERT_HEAD(&newSub->monitoredItems, mon, listEntry);
40901 }
40902 sub->monitoredItemsSize = 0;
40903
40904 /* Move over the notification queue */
40905 TAILQ_INIT(&newSub->notificationQueue);
40906 UA_Notification *nn, *nn_tmp;
40907 TAILQ_FOREACH_SAFE(nn, &sub->notificationQueue, globalEntry, nn_tmp) {
40908 TAILQ_REMOVE(&sub->notificationQueue, nn, globalEntry);
40909 TAILQ_INSERT_TAIL(&newSub->notificationQueue, nn, globalEntry);
40910 }
40911 sub->notificationQueueSize = 0;
40912 sub->dataChangeNotifications = 0;
40913 sub->eventNotifications = 0;
40914
40915 TAILQ_INIT(&newSub->retransmissionQueue);
40916 UA_NotificationMessageEntry *nme, *nme_tmp;
40917 TAILQ_FOREACH_SAFE(nme, &sub->retransmissionQueue, listEntry, nme_tmp) {
40918 TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry);
40919 TAILQ_INSERT_TAIL(&newSub->retransmissionQueue, nme, listEntry);
40920 if(oldSession)
40921 oldSession->totalRetransmissionQueueSize -= 1;
40922 sub->retransmissionQueueSize -= 1;
40923 }
40924 UA_assert(sub->retransmissionQueueSize == 0);
40925 sub->retransmissionQueueSize = 0;
40926
40927 /* Add to the server */
40928 UA_assert(newSub->subscriptionId == sub->subscriptionId);
40929 LIST_INSERT_HEAD(&server->subscriptions, newSub, serverListEntry);
40930 server->subscriptionsSize++;
40931
40932 /* Attach to the session */
40933 UA_Session_attachSubscription(session, sub: newSub);
40934
40935 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, newSub, "Transferred to this Session");
40936
40937 /* Set StatusChange in the original subscription and force publish. This
40938 * also removes the Subscription, even if there was no PublishResponse
40939 * queued to send a StatusChangeNotification. */
40940 sub->statusChange = UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED;
40941 UA_Subscription_publish(server, sub);
40942
40943 /* The original subscription has been deactivated */
40944 UA_assert(sub->publishCallbackId == 0);
40945
40946 /* Re-create notifications with the current values for the new subscription */
40947 if(*sendInitialValues) {
40948 LIST_FOREACH(mon, &newSub->monitoredItems, listEntry) {
40949
40950 /* Create only DataChange notifications */
40951 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
40952 continue;
40953
40954 /* Only if the mode is monitoring */
40955 if(mon->monitoringMode != UA_MONITORINGMODE_REPORTING)
40956 continue;
40957
40958 /* If a value is queued for a data MonitoredItem, the next value in
40959 * the queue is sent in the Publish response. */
40960 if(mon->queueSize > 0)
40961 continue;
40962
40963 /* Create a notification with the last sampled value */
40964 UA_MonitoredItem_createDataChangeNotification(server, sub: newSub, mon,
40965 value: &mon->lastValue);
40966 }
40967 }
40968
40969 /* Do not update the statistics for the number of Subscriptions here. The
40970 * fact that we duplicate the subscription and move over the content is just
40971 * an implementtion detail.
40972 * server->serverDiagnosticsSummary.currentSubscriptionCount++;
40973 * server->serverDiagnosticsSummary.cumulatedSubscriptionCount++;
40974 *
40975 * Update the diagnostics statistics: */
40976#ifdef UA_ENABLE_DIAGNOSTICS
40977 if(oldSession &&
40978 UA_order(&oldSession->clientDescription,
40979 &session->clientDescription,
40980 &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]) == UA_ORDER_EQ)
40981 sub->transferredToSameClientCount++;
40982 else
40983 sub->transferredToAltClientCount++;
40984#endif
40985
40986 /* Immediately try to publish on the new Subscription. This might put it
40987 * into the "late subscription" mode. */
40988 UA_Subscription_publish(server, sub: newSub);
40989}
40990
40991void Service_TransferSubscriptions(UA_Server *server, UA_Session *session,
40992 const UA_TransferSubscriptionsRequest *request,
40993 UA_TransferSubscriptionsResponse *response) {
40994 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40995 "Processing TransferSubscriptionsRequest");
40996 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40997
40998 response->responseHeader.serviceResult =
40999 UA_Server_processServiceOperations(server, session,
41000 operationCallback: (UA_ServiceOperation)Operation_TransferSubscription,
41001 context: &request->sendInitialValues,
41002 requestOperations: &request->subscriptionIdsSize, requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
41003 responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_TRANSFERRESULT]);
41004}
41005
41006#endif /* UA_ENABLE_SUBSCRIPTIONS */
41007
41008/**** amalgamated original file "/src/server/ua_services_monitoreditem.c" ****/
41009
41010/* This Source Code Form is subject to the terms of the Mozilla Public
41011 * License, v. 2.0. If a copy of the MPL was not distributed with this
41012 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
41013 *
41014 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
41015 * Copyright 2016-2017 (c) Florian Palm
41016 * Copyright 2015 (c) Chris Iatrou
41017 * Copyright 2015-2016 (c) Sten Grüner
41018 * Copyright 2015-2016 (c) Oleksiy Vasylyev
41019 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
41020 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
41021 * Copyright 2017 (c) Mattias Bornhager
41022 * Copyright 2017 (c) Henrik Norrman
41023 * Copyright 2017-2023 (c) Thomas Stalder, Blue Time Concept SA
41024 * Copyright 2018 (c) Fabian Arndt, Root-Core
41025 * Copyright 2020 (c) Kalycito Infotech Private Limited
41026 * Copyright 2021 (c) Uranik, Berisha
41027 * Copyright 2021 (c) Ammar, Morshed
41028 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
41029 */
41030
41031
41032#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
41033
41034#ifdef UA_ENABLE_DA
41035
41036/* Translate a percentage deadband into an absolute deadband based on the
41037 * UARange property of the variable */
41038static UA_StatusCode
41039setAbsoluteFromPercentageDeadband(UA_Server *server, UA_Session *session,
41040 const UA_MonitoredItem *mon, UA_DataChangeFilter *filter) {
41041 /* A valid deadband? */
41042 if(filter->deadbandValue < 0.0 || filter->deadbandValue > 100.0)
41043 return UA_STATUSCODE_BADDEADBANDFILTERINVALID;
41044
41045 /* Browse for the percent range */
41046 UA_QualifiedName qn = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EURange");
41047 UA_BrowsePathResult bpr =
41048 browseSimplifiedBrowsePath(server, origin: mon->itemToMonitor.nodeId, browsePathSize: 1, browsePath: &qn);
41049 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
41050 UA_BrowsePathResult_clear(p: &bpr);
41051 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41052 }
41053
41054 /* Read the range */
41055 UA_ReadValueId rvi;
41056 UA_ReadValueId_init(p: &rvi);
41057 rvi.nodeId = bpr.targets->targetId.nodeId;
41058 rvi.attributeId = UA_ATTRIBUTEID_VALUE;
41059 UA_DataValue rangeVal = UA_Server_readWithSession(server, session, item: &rvi,
41060 timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER);
41061 UA_BrowsePathResult_clear(p: &bpr);
41062 if(!UA_Variant_isScalar(v: &rangeVal.value) ||
41063 rangeVal.value.type != &UA_TYPES[UA_TYPES_RANGE]) {
41064 UA_DataValue_clear(p: &rangeVal);
41065 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41066 }
41067
41068 /* Compute the abs deadband */
41069 UA_Range *euRange = (UA_Range*)rangeVal.value.data;
41070 UA_Double absDeadband = (filter->deadbandValue/100.0) * (euRange->high - euRange->low);
41071
41072 UA_DataValue_clear(p: &rangeVal);
41073
41074 /* EURange invalid or NaN? */
41075 if(absDeadband < 0.0 || absDeadband != absDeadband) {
41076 UA_DataValue_clear(p: &rangeVal);
41077 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41078 }
41079
41080 /* Adjust the original filter */
41081 filter->deadbandType = UA_DEADBANDTYPE_ABSOLUTE;
41082 filter->deadbandValue = absDeadband;
41083 return UA_STATUSCODE_GOOD;
41084}
41085
41086#endif /* UA_ENABLE_DA */
41087
41088void
41089Service_SetTriggering(UA_Server *server, UA_Session *session,
41090 const UA_SetTriggeringRequest *request,
41091 UA_SetTriggeringResponse *response) {
41092 /* Nothing to do? */
41093 if(request->linksToRemoveSize == 0 &&
41094 request->linksToAddSize == 0) {
41095 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
41096 return;
41097 }
41098
41099 /* Get the Subscription */
41100 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41101 if(!sub) {
41102 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41103 return;
41104 }
41105
41106 /* Get the MonitoredItem */
41107 UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: request->triggeringItemId);
41108 if(!mon) {
41109 response->responseHeader.serviceResult = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41110 return;
41111 }
41112
41113 /* Allocate the results arrays */
41114 if(request->linksToRemoveSize > 0) {
41115 response->removeResults = (UA_StatusCode*)
41116 UA_Array_new(size: request->linksToRemoveSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
41117 if(!response->removeResults) {
41118 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
41119 return;
41120 }
41121 response->removeResultsSize = request->linksToRemoveSize;
41122 }
41123
41124 if(request->linksToAddSize> 0) {
41125 response->addResults = (UA_StatusCode*)
41126 UA_Array_new(size: request->linksToAddSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
41127 if(!response->addResults) {
41128 UA_Array_delete(p: response->removeResults,
41129 size: request->linksToAddSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
41130 response->removeResults = NULL;
41131 response->removeResultsSize = 0;
41132 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
41133 return;
41134 }
41135 response->addResultsSize = request->linksToAddSize;
41136 }
41137
41138 /* Apply the changes */
41139 for(size_t i = 0; i < request->linksToRemoveSize; i++)
41140 response->removeResults[i] =
41141 UA_MonitoredItem_removeLink(sub, mon, linkId: request->linksToRemove[i]);
41142
41143 for(size_t i = 0; i < request->linksToAddSize; i++)
41144 response->addResults[i] =
41145 UA_MonitoredItem_addLink(sub, mon, linkId: request->linksToAdd[i]);
41146}
41147
41148/* Verify and adjust the parameters of a MonitoredItem */
41149static UA_StatusCode
41150checkAdjustMonitoredItemParams(UA_Server *server, UA_Session *session,
41151 const UA_MonitoredItem *mon,
41152 const UA_DataType* valueType,
41153 UA_MonitoringParameters *params) {
41154 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41155
41156 /* Check the filter */
41157 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
41158 /* Event MonitoredItems need a filter */
41159#ifndef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41160 return UA_STATUSCODE_BADNOTSUPPORTED;
41161#else
41162 if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED &&
41163 params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE)
41164 return UA_STATUSCODE_BADEVENTFILTERINVALID;
41165 if(params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER])
41166 return UA_STATUSCODE_BADEVENTFILTERINVALID;
41167#endif
41168 } else {
41169 /* DataChange MonitoredItem. Can be "no filter" which defaults to
41170 * triggering on Status and Value. */
41171 if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED &&
41172 params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE &&
41173 params->filter.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY)
41174 return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
41175
41176 /* If the filter ExtensionObject has a body, then it must be a
41177 * DataChangeFilter */
41178 if(params->filter.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY &&
41179 params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_DATACHANGEFILTER])
41180 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41181
41182 /* Check the deadband and adjust if necessary. */
41183 if(params->filter.content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) {
41184 UA_DataChangeFilter *filter = (UA_DataChangeFilter *)
41185 params->filter.content.decoded.data;
41186 switch(filter->deadbandType) {
41187 case UA_DEADBANDTYPE_NONE:
41188 break;
41189 case UA_DEADBANDTYPE_ABSOLUTE:
41190 if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE ||
41191 !valueType || !UA_DataType_isNumeric(type: valueType))
41192 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41193 break;
41194#ifdef UA_ENABLE_DA
41195 case UA_DEADBANDTYPE_PERCENT: {
41196 if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE ||
41197 !valueType || !UA_DataType_isNumeric(type: valueType))
41198 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41199 /* If percentage deadband is supported, look up the range values
41200 * and precompute as if it was an absolute deadband. */
41201 UA_StatusCode res =
41202 setAbsoluteFromPercentageDeadband(server, session, mon, filter);
41203 if(res != UA_STATUSCODE_GOOD)
41204 return res;
41205 break;
41206 }
41207#endif
41208 default:
41209 return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
41210 }
41211 }
41212 }
41213
41214 /* Read the minimum sampling interval for the variable. The sampling
41215 * interval of the MonitoredItem must not be less than that. */
41216 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_VALUE) {
41217 const UA_Node *node = UA_NODESTORE_GET(server, &mon->itemToMonitor.nodeId);
41218 if(node) {
41219 const UA_VariableNode *vn = &node->variableNode;
41220 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
41221 /* Take into account if the publishing interval is used for sampling */
41222 UA_Double samplingInterval = params->samplingInterval;
41223 if(samplingInterval < 0 && mon->subscription)
41224 samplingInterval = mon->subscription->publishingInterval;
41225 /* Adjust if smaller than the allowed minimum for the variable */
41226 if(samplingInterval < vn->minimumSamplingInterval)
41227 params->samplingInterval = vn->minimumSamplingInterval;
41228 }
41229 UA_NODESTORE_RELEASE(server, node);
41230 }
41231 }
41232
41233 /* Adjust sampling interval */
41234 if(params->samplingInterval < 0.0) {
41235 /* A negative number indicates that the sampling interval is the
41236 * publishing interval of the Subscription. */
41237 if(!mon->subscription) {
41238 /* Not possible for local MonitoredItems */
41239 params->samplingInterval = server->config.samplingIntervalLimits.min;
41240 } else {
41241 /* Test if the publishing interval is a valid sampling interval. If
41242 * not, adjust to lie within the limits. */
41243 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits,
41244 mon->subscription->publishingInterval,
41245 params->samplingInterval);
41246 if(params->samplingInterval == mon->subscription->publishingInterval) {
41247 /* The publishing interval is valid also for sampling. The
41248 * standard says any negative number is interpreted as -1.*/
41249 params->samplingInterval = -1.0;
41250 }
41251 }
41252 } else {
41253 /* Adjust positive sampling interval to lie within the limits */
41254 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits,
41255 params->samplingInterval, params->samplingInterval);
41256 /* Check for NaN */
41257 if(mon->parameters.samplingInterval != mon->parameters.samplingInterval)
41258 params->samplingInterval = server->config.samplingIntervalLimits.min;
41259 }
41260
41261 /* Adjust the maximum queue size */
41262#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41263 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
41264 /* 0 => Set to the configured maximum. Otherwise adjust with configured limits */
41265 if(params->queueSize == 0) {
41266 params->queueSize = server->config.queueSizeLimits.max;
41267 } else {
41268 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
41269 params->queueSize, params->queueSize);
41270 }
41271 } else
41272#endif
41273 {
41274 /* 0 or 1 => queue-size 1. Otherwise adjust with configured limits */
41275 if(params->queueSize == 0)
41276 params->queueSize = 1;
41277 if(params->queueSize != 1)
41278 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
41279 params->queueSize, params->queueSize);
41280 }
41281
41282 return UA_STATUSCODE_GOOD;
41283}
41284
41285#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41286static UA_StatusCode
41287checkEventFilterParam(UA_Server *server, UA_Session *session,
41288 const UA_MonitoredItem *mon,
41289 UA_MonitoringParameters *params){
41290 if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
41291 return UA_STATUSCODE_GOOD;
41292
41293 UA_EventFilter *eventFilter =
41294 (UA_EventFilter *) params->filter.content.decoded.data;
41295
41296 if(eventFilter == NULL)
41297 return UA_STATUSCODE_BADEVENTFILTERINVALID;
41298
41299 //TODO make the maximum select clause size param an server-config parameter
41300 if(eventFilter->selectClausesSize > 128)
41301 return UA_STATUSCODE_BADCONFIGURATIONERROR;
41302
41303 //check the where clause for logical consistency
41304 if(eventFilter->whereClause.elementsSize != 0) {
41305 UA_ContentFilterResult contentFilterResult;
41306 UA_Event_staticWhereClauseValidation(server, filter: &eventFilter->whereClause,
41307 &contentFilterResult);
41308 for(size_t i = 0; i < contentFilterResult.elementResultsSize; ++i) {
41309 if(contentFilterResult.elementResults[i].statusCode != UA_STATUSCODE_GOOD){
41310 //ToDo currently we return the first non good status code, check if
41311 //we can use the detailed contentFilterResult later
41312 UA_StatusCode whereResult =
41313 contentFilterResult.elementResults[i].statusCode;
41314 UA_ContentFilterResult_clear(p: &contentFilterResult);
41315 return whereResult;
41316 }
41317 }
41318 UA_ContentFilterResult_clear(p: &contentFilterResult);
41319 }
41320 //check the select clause for logical consistency
41321 UA_StatusCode selectClauseValidationResult[128];
41322 UA_Event_staticSelectClauseValidation(server,eventFilter,
41323 result: selectClauseValidationResult);
41324 for(size_t i = 0; i < eventFilter->selectClausesSize; ++i){
41325 //ToDo currently we return the first non good status code, check if
41326 //we can use the detailed status code list later
41327 if(selectClauseValidationResult[i] != UA_STATUSCODE_GOOD){
41328 return selectClauseValidationResult[i];
41329 }
41330 }
41331
41332 return UA_STATUSCODE_GOOD;
41333}
41334#endif
41335
41336static const UA_String
41337binaryEncoding = {sizeof("Default Binary") - 1, (UA_Byte *)"Default Binary"};
41338
41339/* Structure to pass additional arguments into the operation */
41340struct createMonContext {
41341 UA_Subscription *sub;
41342 UA_TimestampsToReturn timestampsToReturn;
41343
41344 /* If sub is NULL, use local callbacks */
41345 UA_Server_DataChangeNotificationCallback dataChangeCallback;
41346 void *context;
41347};
41348
41349static void
41350Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session,
41351 struct createMonContext *cmc,
41352 const UA_MonitoredItemCreateRequest *request,
41353 UA_MonitoredItemCreateResult *result) {
41354 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41355
41356 /* Check available capacity */
41357 if(cmc->sub &&
41358 (((server->config.maxMonitoredItems != 0) &&
41359 (server->monitoredItemsSize >= server->config.maxMonitoredItems)) ||
41360 ((server->config.maxMonitoredItemsPerSubscription != 0) &&
41361 (cmc->sub->monitoredItemsSize >= server->config.maxMonitoredItemsPerSubscription)))) {
41362 result->statusCode = UA_STATUSCODE_BADTOOMANYMONITOREDITEMS;
41363 return;
41364 }
41365
41366 /* Check if the encoding is supported */
41367 if(request->itemToMonitor.dataEncoding.name.length > 0 &&
41368 (!UA_String_equal(s1: &binaryEncoding, s2: &request->itemToMonitor.dataEncoding.name) ||
41369 request->itemToMonitor.dataEncoding.namespaceIndex != 0)) {
41370 result->statusCode = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED;
41371 return;
41372 }
41373
41374 /* Check if the encoding is set for a value */
41375 if(request->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE &&
41376 request->itemToMonitor.dataEncoding.name.length > 0) {
41377 result->statusCode = UA_STATUSCODE_BADDATAENCODINGINVALID;
41378 return;
41379 }
41380
41381 /* Make an example read to check the itemToMonitor. The DataSource itself
41382 * could return a (temporary) error. This should still result in a valid
41383 * MonitoredItem. Only a few StatusCodes are considered unrecoverable and
41384 * lead to an abort:
41385 * - The Node does not exist
41386 * - The AttributeId does not match the NodeClass
41387 * - The Session does not have sufficient access rights
41388 * - The indicated encoding is not supported or not valid */
41389 UA_DataValue v = UA_Server_readWithSession(server, session, item: &request->itemToMonitor,
41390 timestampsToReturn: cmc->timestampsToReturn);
41391 if(v.hasStatus &&
41392 (v.status == UA_STATUSCODE_BADNODEIDUNKNOWN ||
41393 v.status == UA_STATUSCODE_BADATTRIBUTEIDINVALID ||
41394 v.status == UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED ||
41395 v.status == UA_STATUSCODE_BADDATAENCODINGINVALID ||
41396 v.status == UA_STATUSCODE_BADINDEXRANGEINVALID
41397 /* Part 4, 5.12.2 CreateMonitoredItems: When a user adds a monitored
41398 * item that the user is denied read access to, the add operation for
41399 * the item shall succeed and the bad status Bad_NotReadable or
41400 * Bad_UserAccessDenied shall be returned in the Publish response.
41401 * v.status == UA_STATUSCODE_BADNOTREADABLE
41402 * v.status == UA_STATUSCODE_BADUSERACCESSDENIED
41403 *
41404 * The IndexRange error can change depending on the value.
41405 * v.status == UA_STATUSCODE_BADINDEXRANGENODATA */
41406 )) {
41407 result->statusCode = v.status;
41408 UA_DataValue_clear(p: &v);
41409 return;
41410 }
41411
41412 /* Adding an Event MonitoredItem */
41413#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41414 if(request->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
41415 /* TODO: Only remote clients can add Event-MonitoredItems at the moment */
41416 if(!cmc->sub) {
41417 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
41418 msg: "Only remote clients can add Event-MonitoredItems");
41419 result->statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
41420 UA_DataValue_clear(p: &v);
41421 return;
41422 }
41423
41424 /* If the 'SubscribeToEvents' bit of EventNotifier attribute is
41425 * zero, then the object cannot be subscribed to monitor events */
41426 if(!v.hasValue || !v.value.data) {
41427 result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
41428 UA_DataValue_clear(p: &v);
41429 return;
41430 }
41431 UA_Byte eventNotifierValue = *((UA_Byte *)v.value.data);
41432 if((eventNotifierValue & 0x01) != 1) {
41433 result->statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
41434 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
41435 "Could not create a MonitoredItem as the "
41436 "'SubscribeToEvents' bit of the EventNotifier "
41437 "attribute is not set");
41438 UA_DataValue_clear(p: &v);
41439 return;
41440 }
41441 }
41442#endif
41443
41444 const UA_DataType *valueType = v.value.type;
41445 UA_DataValue_clear(p: &v);
41446
41447 /* Allocate the MonitoredItem */
41448 UA_MonitoredItem *newMon = NULL;
41449 if(cmc->sub) {
41450 newMon = (UA_MonitoredItem*)UA_malloc(size: sizeof(UA_MonitoredItem));
41451 } else {
41452 UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*)
41453 UA_malloc(size: sizeof(UA_LocalMonitoredItem));
41454 if(localMon) {
41455 /* Set special values only for the LocalMonitoredItem */
41456 localMon->context = cmc->context;
41457 localMon->callback.dataChangeCallback = cmc->dataChangeCallback;
41458 }
41459 newMon = &localMon->monitoredItem;
41460 }
41461 if(!newMon) {
41462 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
41463 return;
41464 }
41465
41466 /* Initialize the MonitoredItem */
41467 UA_MonitoredItem_init(mon: newMon);
41468 newMon->subscription = cmc->sub; /* Can be NULL for local MonitoredItems */
41469 newMon->timestampsToReturn = cmc->timestampsToReturn;
41470 result->statusCode |= UA_ReadValueId_copy(src: &request->itemToMonitor,
41471 dst: &newMon->itemToMonitor);
41472 result->statusCode |= UA_MonitoringParameters_copy(src: &request->requestedParameters,
41473 dst: &newMon->parameters);
41474 result->statusCode |= checkAdjustMonitoredItemParams(server, session, mon: newMon,
41475 valueType, params: &newMon->parameters);
41476#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41477 result->statusCode |= checkEventFilterParam(server, session, mon: newMon,
41478 params: &newMon->parameters);
41479#endif
41480 if(result->statusCode != UA_STATUSCODE_GOOD) {
41481 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
41482 "Could not create a MonitoredItem "
41483 "with StatusCode %s",
41484 UA_StatusCode_name(result->statusCode));
41485 UA_MonitoredItem_delete(server, monitoredItem: newMon);
41486 return;
41487 }
41488
41489 /* Initialize the value status so the first sample always passes the filter */
41490 newMon->lastValue.hasStatus = true;
41491 newMon->lastValue.status = ~(UA_StatusCode)0;
41492
41493 /* Register the Monitoreditem in the server and subscription */
41494 UA_Server_registerMonitoredItem(server, mon: newMon);
41495
41496 /* Activate the MonitoredItem */
41497 result->statusCode |=
41498 UA_MonitoredItem_setMonitoringMode(server, mon: newMon, monitoringMode: request->monitoringMode);
41499 if(result->statusCode != UA_STATUSCODE_GOOD) {
41500 UA_MonitoredItem_delete(server, monitoredItem: newMon);
41501 return;
41502 }
41503
41504 /* Prepare the response */
41505 result->revisedSamplingInterval = newMon->parameters.samplingInterval;
41506 result->revisedQueueSize = newMon->parameters.queueSize;
41507 result->monitoredItemId = newMon->monitoredItemId;
41508
41509 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
41510 "MonitoredItem %" PRIi32 " | "
41511 "Created the MonitoredItem "
41512 "(Sampling Interval: %.2fms, Queue Size: %lu)",
41513 newMon->monitoredItemId,
41514 newMon->parameters.samplingInterval,
41515 (unsigned long)newMon->parameters.queueSize);
41516}
41517
41518void
41519Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
41520 const UA_CreateMonitoredItemsRequest *request,
41521 UA_CreateMonitoredItemsResponse *response) {
41522 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
41523 "Processing CreateMonitoredItemsRequest");
41524 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41525
41526 if(server->config.maxMonitoredItemsPerCall != 0 &&
41527 request->itemsToCreateSize > server->config.maxMonitoredItemsPerCall) {
41528 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
41529 return;
41530 }
41531
41532 /* Check if the timestampstoreturn is valid */
41533 struct createMonContext cmc;
41534 cmc.timestampsToReturn = request->timestampsToReturn;
41535 if(cmc.timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
41536 response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
41537 return;
41538 }
41539
41540 /* Find the subscription */
41541 cmc.sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41542 if(!cmc.sub) {
41543 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41544 return;
41545 }
41546
41547 /* Reset the subscription lifetime */
41548 cmc.sub->currentLifetimeCount = 0;
41549
41550 response->responseHeader.serviceResult =
41551 UA_Server_processServiceOperations(server, session,
41552 operationCallback: (UA_ServiceOperation)Operation_CreateMonitoredItem,
41553 context: &cmc, requestOperations: &request->itemsToCreateSize,
41554 requestOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST],
41555 responseOperations: &response->resultsSize,
41556 responseOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
41557}
41558
41559UA_MonitoredItemCreateResult
41560UA_Server_createDataChangeMonitoredItem(UA_Server *server,
41561 UA_TimestampsToReturn timestampsToReturn,
41562 const UA_MonitoredItemCreateRequest item,
41563 void *monitoredItemContext,
41564 UA_Server_DataChangeNotificationCallback callback) {
41565 struct createMonContext cmc;
41566 cmc.sub = NULL;
41567 cmc.context = monitoredItemContext;
41568 cmc.dataChangeCallback = callback;
41569 cmc.timestampsToReturn = timestampsToReturn;
41570
41571 UA_MonitoredItemCreateResult result;
41572 UA_MonitoredItemCreateResult_init(p: &result);
41573 UA_LOCK(&server->serviceMutex);
41574 Operation_CreateMonitoredItem(server, session: &server->adminSession, cmc: &cmc, request: &item, result: &result);
41575 UA_UNLOCK(&server->serviceMutex);
41576 return result;
41577}
41578
41579static void
41580Operation_ModifyMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub,
41581 const UA_MonitoredItemModifyRequest *request,
41582 UA_MonitoredItemModifyResult *result) {
41583 /* Get the MonitoredItem */
41584 UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: request->monitoredItemId);
41585 if(!mon) {
41586 result->statusCode = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41587 return;
41588 }
41589
41590 /* Make local copy of the settings */
41591 UA_MonitoringParameters params;
41592 result->statusCode =
41593 UA_MonitoringParameters_copy(src: &request->requestedParameters, dst: &params);
41594 if(result->statusCode != UA_STATUSCODE_GOOD)
41595 return;
41596
41597 /* Read the current value to test if filters are possible.
41598 * Can return an empty value (v.value.type == NULL). */
41599 UA_DataValue v =
41600 UA_Server_readWithSession(server, session, item: &mon->itemToMonitor,
41601 timestampsToReturn: mon->timestampsToReturn);
41602
41603 /* Verify and adjust the new parameters. This still leaves the original
41604 * MonitoredItem untouched. */
41605 result->statusCode =
41606 checkAdjustMonitoredItemParams(server, session, mon,
41607 valueType: v.value.type, params: &params);
41608 UA_DataValue_clear(p: &v);
41609 if(result->statusCode != UA_STATUSCODE_GOOD) {
41610 UA_MonitoringParameters_clear(p: &params);
41611 return;
41612 }
41613
41614 /* Store the old sampling interval */
41615 UA_Double oldSamplingInterval = mon->parameters.samplingInterval;
41616
41617 /* Move over the new settings */
41618 UA_MonitoringParameters_clear(p: &mon->parameters);
41619 mon->parameters = params;
41620
41621 /* Re-register the callback if necessary */
41622 if(oldSamplingInterval != mon->parameters.samplingInterval) {
41623 UA_MonitoredItem_unregisterSampling(server, mon);
41624 result->statusCode =
41625 UA_MonitoredItem_setMonitoringMode(server, mon, monitoringMode: mon->monitoringMode);
41626 }
41627
41628 result->revisedSamplingInterval = mon->parameters.samplingInterval;
41629 result->revisedQueueSize = mon->parameters.queueSize;
41630
41631 /* Remove some notifications if the queue is now too small */
41632 UA_MonitoredItem_ensureQueueSpace(server, mon);
41633
41634 /* Remove the overflow bits if the queue has now a size of 1 */
41635 UA_MonitoredItem_removeOverflowInfoBits(mon);
41636
41637 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
41638 "MonitoredItem %" PRIi32 " | "
41639 "Modified the MonitoredItem "
41640 "(Sampling Interval: %fms, Queue Size: %lu)",
41641 mon->monitoredItemId,
41642 mon->parameters.samplingInterval,
41643 (unsigned long)mon->queueSize);
41644}
41645
41646void
41647Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
41648 const UA_ModifyMonitoredItemsRequest *request,
41649 UA_ModifyMonitoredItemsResponse *response) {
41650 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
41651 "Processing ModifyMonitoredItemsRequest");
41652 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41653
41654 if(server->config.maxMonitoredItemsPerCall != 0 &&
41655 request->itemsToModifySize > server->config.maxMonitoredItemsPerCall) {
41656 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
41657 return;
41658 }
41659
41660 /* Check if the timestampstoreturn is valid */
41661 if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
41662 response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
41663 return;
41664 }
41665
41666 /* Get the subscription */
41667 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41668 if(!sub) {
41669 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41670 return;
41671 }
41672
41673 sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
41674
41675 response->responseHeader.serviceResult =
41676 UA_Server_processServiceOperations(server, session,
41677 operationCallback: (UA_ServiceOperation)Operation_ModifyMonitoredItem,
41678 context: sub, requestOperations: &request->itemsToModifySize,
41679 requestOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST],
41680 responseOperations: &response->resultsSize,
41681 responseOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]);
41682}
41683
41684struct setMonitoringContext {
41685 UA_Subscription *sub;
41686 UA_MonitoringMode monitoringMode;
41687};
41688
41689static void
41690Operation_SetMonitoringMode(UA_Server *server, UA_Session *session,
41691 struct setMonitoringContext *smc,
41692 const UA_UInt32 *monitoredItemId, UA_StatusCode *result) {
41693 UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub: smc->sub, monitoredItemId: *monitoredItemId);
41694 if(!mon) {
41695 *result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41696 return;
41697 }
41698 *result = UA_MonitoredItem_setMonitoringMode(server, mon, monitoringMode: smc->monitoringMode);
41699}
41700
41701void
41702Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
41703 const UA_SetMonitoringModeRequest *request,
41704 UA_SetMonitoringModeResponse *response) {
41705 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing SetMonitoringMode");
41706 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41707
41708 if(server->config.maxMonitoredItemsPerCall != 0 &&
41709 request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) {
41710 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
41711 return;
41712 }
41713
41714 /* Get the subscription */
41715 struct setMonitoringContext smc;
41716 smc.sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41717 if(!smc.sub) {
41718 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41719 return;
41720 }
41721
41722 smc.sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
41723
41724 smc.monitoringMode = request->monitoringMode;
41725 response->responseHeader.serviceResult =
41726 UA_Server_processServiceOperations(server, session,
41727 operationCallback: (UA_ServiceOperation)Operation_SetMonitoringMode,
41728 context: &smc, requestOperations: &request->monitoredItemIdsSize,
41729 requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
41730 responseOperations: &response->resultsSize,
41731 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
41732}
41733
41734static void
41735Operation_DeleteMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub,
41736 const UA_UInt32 *monitoredItemId, UA_StatusCode *result) {
41737 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41738 UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: *monitoredItemId);
41739 if(!mon) {
41740 *result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41741 return;
41742 }
41743 UA_MonitoredItem_delete(server, monitoredItem: mon);
41744}
41745
41746void
41747Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
41748 const UA_DeleteMonitoredItemsRequest *request,
41749 UA_DeleteMonitoredItemsResponse *response) {
41750 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
41751 "Processing DeleteMonitoredItemsRequest");
41752 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41753
41754 if(server->config.maxMonitoredItemsPerCall != 0 &&
41755 request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) {
41756 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
41757 return;
41758 }
41759
41760 /* Get the subscription */
41761 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41762 if(!sub) {
41763 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41764 return;
41765 }
41766
41767 /* Reset the subscription lifetime */
41768 sub->currentLifetimeCount = 0;
41769
41770 response->responseHeader.serviceResult =
41771 UA_Server_processServiceOperations(server, session,
41772 operationCallback: (UA_ServiceOperation)Operation_DeleteMonitoredItem,
41773 context: sub, requestOperations: &request->monitoredItemIdsSize,
41774 requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
41775 responseOperations: &response->resultsSize,
41776 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
41777}
41778
41779UA_StatusCode
41780UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId) {
41781 UA_LOCK(&server->serviceMutex);
41782 UA_MonitoredItem *mon, *mon_tmp;
41783 LIST_FOREACH_SAFE(mon, &server->localMonitoredItems, listEntry, mon_tmp) {
41784 if(mon->monitoredItemId != monitoredItemId)
41785 continue;
41786 UA_MonitoredItem_delete(server, monitoredItem: mon);
41787 UA_UNLOCK(&server->serviceMutex);
41788 return UA_STATUSCODE_GOOD;
41789 }
41790 UA_UNLOCK(&server->serviceMutex);
41791 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41792}
41793
41794#endif /* UA_ENABLE_SUBSCRIPTIONS */
41795
41796/**** amalgamated original file "/src/server/ua_services_securechannel.c" ****/
41797
41798/* This Source Code Form is subject to the terms of the Mozilla Public
41799 * License, v. 2.0. If a copy of the MPL was not distributed with this
41800 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
41801 *
41802 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
41803 * Copyright 2014, 2017 (c) Florian Palm
41804 * Copyright 2015 (c) Oleksiy Vasylyev
41805 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
41806 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
41807 */
41808
41809
41810#ifndef container_of
41811#define container_of(ptr, type, member) \
41812 (type *)((uintptr_t)ptr - offsetof(type,member))
41813#endif
41814
41815static void
41816removeSecureChannelCallback(void *_, channel_entry *entry) {
41817 UA_SecureChannel_close(channel: &entry->channel);
41818}
41819
41820/* Half-closes the channel. Will be completely closed / deleted in a deferred
41821 * callback. Deferring is necessary so we don't remove lists that are still
41822 * processed upwards the call stack. */
41823static void
41824removeSecureChannel(UA_Server *server, channel_entry *entry,
41825 UA_DiagnosticEvent event) {
41826 if(entry->channel.state == UA_SECURECHANNELSTATE_CLOSING)
41827 return;
41828 entry->channel.state = UA_SECURECHANNELSTATE_CLOSING;
41829
41830 /* Detach from the connection and close the connection */
41831 if(entry->channel.connection) {
41832 if(entry->channel.connection->state != UA_CONNECTIONSTATE_CLOSED)
41833 entry->channel.connection->close(entry->channel.connection);
41834 UA_Connection_detachSecureChannel(connection: entry->channel.connection);
41835 }
41836
41837 /* Detach the channel */
41838 TAILQ_REMOVE(&server->channels, entry, pointers);
41839
41840 /* Update the statistics */
41841 UA_SecureChannelStatistics *scs = &server->secureChannelStatistics;
41842 UA_atomic_subSize(addr: &scs->currentChannelCount, decrease: 1);
41843 switch(event) {
41844 case UA_DIAGNOSTICEVENT_CLOSE:
41845 break;
41846 case UA_DIAGNOSTICEVENT_TIMEOUT:
41847 UA_atomic_addSize(addr: &scs->channelTimeoutCount, increase: 1);
41848 break;
41849 case UA_DIAGNOSTICEVENT_PURGE:
41850 UA_atomic_addSize(addr: &scs->channelPurgeCount, increase: 1);
41851 break;
41852 case UA_DIAGNOSTICEVENT_REJECT:
41853 case UA_DIAGNOSTICEVENT_SECURITYREJECT:
41854 UA_atomic_addSize(addr: &scs->rejectedChannelCount, increase: 1);
41855 break;
41856 case UA_DIAGNOSTICEVENT_ABORT:
41857 UA_atomic_addSize(addr: &scs->channelAbortCount, increase: 1);
41858 break;
41859 default:
41860 UA_assert(false);
41861 break;
41862 }
41863
41864 /* Add a delayed callback to remove the channel when the currently
41865 * scheduled jobs have completed */
41866 entry->cleanupCallback.callback = (UA_ApplicationCallback)removeSecureChannelCallback;
41867 entry->cleanupCallback.application = NULL;
41868 entry->cleanupCallback.data = entry;
41869 entry->cleanupCallback.nextTime = UA_DateTime_nowMonotonic() + 1;
41870 entry->cleanupCallback.interval = 0; /* Remove the structure */
41871 UA_Timer_addTimerEntry(t: &server->timer, te: &entry->cleanupCallback, NULL);
41872}
41873
41874void
41875UA_Server_deleteSecureChannels(UA_Server *server) {
41876 channel_entry *entry, *temp;
41877 TAILQ_FOREACH_SAFE(entry, &server->channels, pointers, temp)
41878 removeSecureChannel(server, entry, event: UA_DIAGNOSTICEVENT_CLOSE);
41879}
41880
41881/* remove channels that were not renewed or who have no connection attached */
41882void
41883UA_Server_cleanupTimedOutSecureChannels(UA_Server *server,
41884 UA_DateTime nowMonotonic) {
41885 channel_entry *entry, *temp;
41886 TAILQ_FOREACH_SAFE(entry, &server->channels, pointers, temp) {
41887 /* The channel was closed internally */
41888 if(entry->channel.state == UA_SECURECHANNELSTATE_CLOSED ||
41889 !entry->channel.connection) {
41890 removeSecureChannel(server, entry, event: UA_DIAGNOSTICEVENT_CLOSE);
41891 continue;
41892 }
41893
41894 /* Is the SecurityToken already created? */
41895 if(entry->channel.securityToken.createdAt == 0) {
41896 /* No -> channel is still in progress of being opened, do not remove */
41897 continue;
41898 }
41899
41900 /* Has the SecurityToken timed out? */
41901 UA_DateTime timeout =
41902 entry->channel.securityToken.createdAt +
41903 (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC);
41904
41905 /* There is a new token. But it has not been used by the client so far.
41906 * Do the rollover now instead of shutting the channel down.
41907 *
41908 * Part 4, 5.5.2 says: Servers shall use the existing SecurityToken to
41909 * secure outgoing Messages until the SecurityToken expires or the
41910 * Server receives a Message secured with a new SecurityToken.*/
41911 if(timeout < nowMonotonic &&
41912 entry->channel.renewState == UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER) {
41913 /* Compare with the rollover in checkSymHeader */
41914 entry->channel.renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
41915 entry->channel.securityToken = entry->channel.altSecurityToken;
41916 UA_ChannelSecurityToken_init(p: &entry->channel.altSecurityToken);
41917 UA_SecureChannel_generateLocalKeys(channel: &entry->channel);
41918 generateRemoteKeys(channel: &entry->channel);
41919
41920 /* Use the timeout of the new SecurityToken */
41921 timeout = entry->channel.securityToken.createdAt +
41922 (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC);
41923 }
41924
41925 if(timeout < nowMonotonic) {
41926 UA_LOG_INFO_CHANNEL(&server->config.logger, &entry->channel,
41927 "SecureChannel has timed out");
41928 removeSecureChannel(server, entry, event: UA_DIAGNOSTICEVENT_TIMEOUT);
41929 }
41930 }
41931}
41932
41933/* remove the first channel that has no session attached */
41934static UA_Boolean
41935purgeFirstChannelWithoutSession(UA_Server *server) {
41936 channel_entry *entry;
41937 TAILQ_FOREACH(entry, &server->channels, pointers) {
41938 if(SLIST_FIRST(&entry->channel.sessions))
41939 continue;
41940 UA_LOG_INFO_CHANNEL(&server->config.logger, &entry->channel,
41941 "Channel was purged since maxSecureChannels was "
41942 "reached and channel had no session attached");
41943 removeSecureChannel(server, entry, event: UA_DIAGNOSTICEVENT_PURGE);
41944 return true;
41945 }
41946 return false;
41947}
41948
41949UA_StatusCode
41950UA_Server_createSecureChannel(UA_Server *server, UA_Connection *connection) {
41951 /* connection already has a channel attached. */
41952 if(connection->channel != NULL)
41953 return UA_STATUSCODE_BADINTERNALERROR;
41954
41955 /* Check if there exists a free SC, otherwise try to purge one SC without a
41956 * session the purge has been introduced to pass CTT, it is not clear what
41957 * strategy is expected here */
41958 if((server->secureChannelStatistics.currentChannelCount >=
41959 server->config.maxSecureChannels) &&
41960 !purgeFirstChannelWithoutSession(server))
41961 return UA_STATUSCODE_BADOUTOFMEMORY;
41962
41963 channel_entry *entry = (channel_entry *)UA_malloc(size: sizeof(channel_entry));
41964 if(!entry)
41965 return UA_STATUSCODE_BADOUTOFMEMORY;
41966
41967 /* Channel state is closed (0) */
41968 /* TODO: Use the connection config from the correct network layer */
41969 UA_SecureChannel_init(channel: &entry->channel,
41970 config: &server->config.networkLayers[0].localConnectionConfig);
41971 entry->channel.certificateVerification = &server->config.certificateVerification;
41972 entry->channel.processOPNHeader = UA_Server_configSecureChannel;
41973
41974 TAILQ_INSERT_TAIL(&server->channels, entry, pointers);
41975 UA_Connection_attachSecureChannel(connection, channel: &entry->channel);
41976 server->secureChannelStatistics.currentChannelCount++;
41977 server->secureChannelStatistics.cumulatedChannelCount++;
41978 return UA_STATUSCODE_GOOD;
41979}
41980
41981UA_StatusCode
41982UA_Server_configSecureChannel(void *application, UA_SecureChannel *channel,
41983 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
41984 /* Iterate over available endpoints and choose the correct one */
41985 UA_SecurityPolicy *securityPolicy = NULL;
41986 UA_Server *const server = (UA_Server *const) application;
41987 for(size_t i = 0; i < server->config.securityPoliciesSize; ++i) {
41988 UA_SecurityPolicy *policy = &server->config.securityPolicies[i];
41989 if(!UA_ByteString_equal(string1: &asymHeader->securityPolicyUri, string2: &policy->policyUri))
41990 continue;
41991
41992 UA_StatusCode retval = policy->asymmetricModule.
41993 compareCertificateThumbprint(policy, &asymHeader->receiverCertificateThumbprint);
41994 if(retval != UA_STATUSCODE_GOOD)
41995 continue;
41996
41997 /* We found the correct policy (except for security mode). The endpoint
41998 * needs to be selected by the client / server to match the security
41999 * mode in the endpoint for the session. */
42000 securityPolicy = policy;
42001 break;
42002 }
42003
42004 if(!securityPolicy)
42005 return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
42006
42007 /* Create the channel context and parse the sender (remote) certificate used for the
42008 * secureChannel. */
42009 UA_StatusCode retval =
42010 UA_SecureChannel_setSecurityPolicy(channel, securityPolicy,
42011 remoteCertificate: &asymHeader->senderCertificate);
42012 if(retval != UA_STATUSCODE_GOOD)
42013 return retval;
42014
42015 channel->securityToken.tokenId = server->lastTokenId++;
42016 return UA_STATUSCODE_GOOD;
42017}
42018
42019static UA_StatusCode
42020UA_SecureChannelManager_open(UA_Server *server, UA_SecureChannel *channel,
42021 const UA_OpenSecureChannelRequest *request,
42022 UA_OpenSecureChannelResponse *response) {
42023 if(channel->state != UA_SECURECHANNELSTATE_ACK_SENT) {
42024 UA_LOG_ERROR_CHANNEL(&server->config.logger, channel,
42025 "Called open on already open or closed channel");
42026 return UA_STATUSCODE_BADINTERNALERROR;
42027 }
42028
42029 if(request->securityMode != UA_MESSAGESECURITYMODE_NONE &&
42030 UA_ByteString_equal(string1: &channel->securityPolicy->policyUri, string2: &UA_SECURITY_POLICY_NONE_URI)) {
42031 return UA_STATUSCODE_BADSECURITYMODEREJECTED;
42032 }
42033
42034 channel->securityMode = request->securityMode;
42035 channel->securityToken.channelId = server->lastChannelId++;
42036 channel->securityToken.createdAt = UA_DateTime_nowMonotonic();
42037
42038 /* Set the lifetime. Lifetime 0 -> set the maximum possible */
42039 channel->securityToken.revisedLifetime =
42040 (request->requestedLifetime > server->config.maxSecurityTokenLifetime) ?
42041 server->config.maxSecurityTokenLifetime : request->requestedLifetime;
42042 if(channel->securityToken.revisedLifetime == 0)
42043 channel->securityToken.revisedLifetime = server->config.maxSecurityTokenLifetime;
42044
42045 UA_StatusCode retval = UA_ByteString_copy(src: &request->clientNonce, dst: &channel->remoteNonce);
42046 if(retval != UA_STATUSCODE_GOOD)
42047 return retval;
42048
42049 /* Generate the nonce. The syymmetric encryption keys are generated when the
42050 * first symmetric message is received */
42051 retval = UA_SecureChannel_generateLocalNonce(channel);
42052 if(retval != UA_STATUSCODE_GOOD)
42053 return retval;
42054
42055 /* Set the response. The token will be revolved to the new token when the
42056 * first symmetric messages is received. */
42057 response->securityToken = channel->securityToken;
42058 response->securityToken.createdAt = UA_DateTime_now(); /* Only for sending */
42059 response->responseHeader.timestamp = response->securityToken.createdAt;
42060 response->responseHeader.requestHandle = request->requestHeader.requestHandle;
42061 retval = UA_ByteString_copy(src: &channel->localNonce, dst: &response->serverNonce);
42062 if(retval != UA_STATUSCODE_GOOD)
42063 return retval;
42064
42065 /* The channel is open */
42066 channel->state = UA_SECURECHANNELSTATE_OPEN;
42067
42068 /* For the first revolve */
42069 channel->renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER;
42070 channel->altSecurityToken = channel->securityToken;
42071 channel->securityToken.tokenId = 0;
42072 return UA_STATUSCODE_GOOD;
42073}
42074
42075static UA_StatusCode
42076UA_SecureChannelManager_renew(UA_Server *server, UA_SecureChannel *channel,
42077 const UA_OpenSecureChannelRequest *request,
42078 UA_OpenSecureChannelResponse *response) {
42079 if(channel->state != UA_SECURECHANNELSTATE_OPEN) {
42080 UA_LOG_ERROR_CHANNEL(&server->config.logger, channel,
42081 "Called renew on channel which is not open");
42082 return UA_STATUSCODE_BADINTERNALERROR;
42083 }
42084
42085 /* Check whether the nonce was reused */
42086 if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE &&
42087 UA_ByteString_equal(string1: &channel->remoteNonce, string2: &request->clientNonce)) {
42088 UA_LOG_ERROR_CHANNEL(&server->config.logger, channel,
42089 "The client reused the last nonce");
42090 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
42091 }
42092
42093 /* Create a new SecurityToken. Will be switched over when the first message
42094 * is received. */
42095 channel->altSecurityToken = channel->securityToken;
42096 channel->altSecurityToken.tokenId = server->lastTokenId++;
42097 channel->altSecurityToken.createdAt = UA_DateTime_nowMonotonic();
42098 channel->altSecurityToken.revisedLifetime =
42099 (request->requestedLifetime > server->config.maxSecurityTokenLifetime) ?
42100 server->config.maxSecurityTokenLifetime : request->requestedLifetime;
42101 if(channel->altSecurityToken.revisedLifetime == 0) /* lifetime 0 -> return the max lifetime */
42102 channel->altSecurityToken.revisedLifetime = server->config.maxSecurityTokenLifetime;
42103
42104 /* Replace the nonces */
42105 UA_ByteString_clear(p: &channel->remoteNonce);
42106 UA_StatusCode retval = UA_ByteString_copy(src: &request->clientNonce, dst: &channel->remoteNonce);
42107 if(retval != UA_STATUSCODE_GOOD)
42108 return retval;
42109
42110 retval = UA_SecureChannel_generateLocalNonce(channel);
42111 if(retval != UA_STATUSCODE_GOOD)
42112 return retval;
42113
42114 /* Set the response */
42115 response->securityToken = channel->altSecurityToken;
42116 response->securityToken.createdAt = UA_DateTime_now(); /* Only for sending */
42117 response->responseHeader.requestHandle = request->requestHeader.requestHandle;
42118 retval = UA_ByteString_copy(src: &channel->localNonce, dst: &response->serverNonce);
42119 if(retval != UA_STATUSCODE_GOOD)
42120 return retval;
42121
42122 channel->renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER;
42123 return UA_STATUSCODE_GOOD;
42124}
42125
42126void
42127UA_Server_closeSecureChannel(UA_Server *server, UA_SecureChannel *channel,
42128 UA_DiagnosticEvent event) {
42129 removeSecureChannel(server, container_of(channel, channel_entry, channel), event);
42130}
42131
42132void
42133Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel *channel,
42134 const UA_OpenSecureChannelRequest *request,
42135 UA_OpenSecureChannelResponse *response) {
42136 if(request->requestType == UA_SECURITYTOKENREQUESTTYPE_RENEW) {
42137 /* Renew the channel */
42138 response->responseHeader.serviceResult =
42139 UA_SecureChannelManager_renew(server, channel, request, response);
42140
42141 /* Logging */
42142 if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
42143 UA_Float lifetime = (UA_Float)response->securityToken.revisedLifetime / 1000;
42144 UA_LOG_INFO_CHANNEL(&server->config.logger, channel, "SecureChannel renewed "
42145 "with a revised lifetime of %.2fs", lifetime);
42146 } else {
42147 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
42148 "Renewing SecureChannel failed");
42149 }
42150 return;
42151 }
42152
42153 /* Must be ISSUE or RENEW */
42154 if(request->requestType != UA_SECURITYTOKENREQUESTTYPE_ISSUE) {
42155 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
42156 return;
42157 }
42158
42159 /* Open the channel */
42160 response->responseHeader.serviceResult =
42161 UA_SecureChannelManager_open(server, channel, request, response);
42162
42163 /* Logging */
42164 if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
42165 UA_Float lifetime = (UA_Float)response->securityToken.revisedLifetime / 1000;
42166 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
42167 "SecureChannel opened with SecurityPolicy %.*s "
42168 "and a revised lifetime of %.2fs",
42169 (int)channel->securityPolicy->policyUri.length,
42170 channel->securityPolicy->policyUri.data, lifetime);
42171 } else {
42172 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
42173 "Opening a SecureChannel failed");
42174 }
42175}
42176
42177/* The server does not send a CloseSecureChannel response */
42178void
42179Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel) {
42180 UA_LOG_INFO_CHANNEL(&server->config.logger, channel, "CloseSecureChannel");
42181 removeSecureChannel(server, container_of(channel, channel_entry, channel),
42182 event: UA_DIAGNOSTICEVENT_CLOSE);
42183}
42184
42185/**** amalgamated original file "/src/server/ua_services_nodemanagement.c" ****/
42186
42187/* This Source Code Form is subject to the terms of the Mozilla Public
42188 * License, v. 2.0. If a copy of the MPL was not distributed with this
42189 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
42190 *
42191 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
42192 * Copyright 2014-2017 (c) Florian Palm
42193 * Copyright 2015-2016 (c) Sten Grüner
42194 * Copyright 2015-2016 (c) Chris Iatrou
42195 * Copyright 2015-2016 (c) Oleksiy Vasylyev
42196 * Copyright 2017 (c) Julian Grothoff
42197 * Copyright 2016 (c) LEvertz
42198 * Copyright 2016 (c) Lorenz Haas
42199 * Copyright 2017 (c) frax2222
42200 * Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
42201 * Copyright 2017 (c) Christian von Arnim
42202 * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
42203 * Copyright 2017 (c) Henrik Norrman
42204 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
42205 */
42206
42207
42208static UA_StatusCode
42209setMethodNode_callback(UA_Server *server,
42210 const UA_NodeId methodNodeId,
42211 UA_MethodCallback methodCallback);
42212
42213/*********************/
42214/* Edit Node Context */
42215/*********************/
42216
42217UA_StatusCode
42218UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId,
42219 void **nodeContext) {
42220 UA_LOCK(&server->serviceMutex);
42221 UA_StatusCode retval = getNodeContext(server, nodeId, nodeContext);
42222 UA_UNLOCK(&server->serviceMutex);
42223 return retval;
42224}
42225
42226UA_StatusCode
42227getNodeContext(UA_Server *server, UA_NodeId nodeId,
42228 void **nodeContext) {
42229 const UA_Node *node = UA_NODESTORE_GET(server, &nodeId);
42230 if(!node)
42231 return UA_STATUSCODE_BADNODEIDUNKNOWN;
42232 *nodeContext = node->head.context;
42233 UA_NODESTORE_RELEASE(server, node);
42234 return UA_STATUSCODE_GOOD;
42235}
42236
42237static UA_StatusCode
42238setDeconstructedNode(UA_Server *server, UA_Session *session,
42239 UA_NodeHead *head, void *context) {
42240 head->constructed = false;
42241 return UA_STATUSCODE_GOOD;
42242}
42243
42244static UA_StatusCode
42245setConstructedNodeContext(UA_Server *server, UA_Session *session,
42246 UA_NodeHead *head, void *context) {
42247 head->context = context;
42248 head->constructed = true;
42249 return UA_STATUSCODE_GOOD;
42250}
42251
42252static UA_StatusCode
42253editNodeContext(UA_Server *server, UA_Session* session,
42254 UA_NodeHead *head, void *context) {
42255 head->context = context;
42256 return UA_STATUSCODE_GOOD;
42257}
42258
42259UA_StatusCode
42260setNodeContext(UA_Server *server, UA_NodeId nodeId,
42261 void *nodeContext) {
42262 return UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
42263 callback: (UA_EditNodeCallback)editNodeContext, data: nodeContext);
42264}
42265
42266UA_StatusCode
42267UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId,
42268 void *nodeContext) {
42269 UA_LOCK(&server->serviceMutex);
42270 UA_StatusCode retval = setNodeContext(server, nodeId, nodeContext);
42271 UA_UNLOCK(&server->serviceMutex);
42272 return retval;
42273}
42274
42275static UA_StatusCode
42276checkSetIsDynamicVariable(UA_Server *server, UA_Session *session,
42277 const UA_NodeId *nodeId);
42278
42279/**********************/
42280/* Consistency Checks */
42281/**********************/
42282
42283#define UA_PARENT_REFERENCES_COUNT 2
42284
42285const UA_NodeId parentReferences[UA_PARENT_REFERENCES_COUNT] = {
42286 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}},
42287 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}
42288};
42289
42290static void
42291logAddNode(const UA_Logger *logger, UA_Session *session,
42292 const UA_NodeId *nodeId, const char *msg) {
42293 UA_LOG_NODEID_INFO(nodeId,
42294 UA_LOG_INFO_SESSION(logger, session, "AddNode (%.*s): %s",
42295 (int)nodeIdStr.length, nodeIdStr.data, msg));
42296}
42297
42298/* Check if the requested parent node exists, has the right node class and is
42299 * referenced with an allowed (hierarchical) reference type. For "type" nodes,
42300 * only hasSubType references are allowed. */
42301static UA_StatusCode
42302checkParentReference(UA_Server *server, UA_Session *session, const UA_NodeHead *head,
42303 const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId) {
42304 /* Objects do not need a parent (e.g. mandatory/optional modellingrules).
42305 * Also, there are some variables which do not have parents, e.g.
42306 * EnumStrings, EnumValues */
42307 if((head->nodeClass == UA_NODECLASS_OBJECT ||
42308 head->nodeClass == UA_NODECLASS_VARIABLE) &&
42309 UA_NodeId_isNull(p: parentNodeId) && UA_NodeId_isNull(p: referenceTypeId))
42310 return UA_STATUSCODE_GOOD;
42311
42312 /* See if the parent exists */
42313 const UA_Node *parent = UA_NODESTORE_GET(server, parentNodeId);
42314 if(!parent) {
42315 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42316 msg: "Parent node not found");
42317 return UA_STATUSCODE_BADPARENTNODEIDINVALID;
42318 }
42319
42320 UA_NodeClass parentNodeClass = parent->head.nodeClass;
42321 UA_NODESTORE_RELEASE(server, parent);
42322
42323 /* Check the referencetype exists */
42324 const UA_Node *referenceType = UA_NODESTORE_GET(server, referenceTypeId);
42325 if(!referenceType) {
42326 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42327 msg: "Reference type to the parent not found");
42328 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
42329 }
42330
42331 /* Check if the referencetype is a reference type node */
42332 if(referenceType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
42333 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42334 msg: "Reference type to the parent is not a ReferenceTypeNode");
42335 UA_NODESTORE_RELEASE(server, referenceType);
42336 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
42337 }
42338
42339 /* Check that the reference type is not abstract */
42340 UA_Boolean referenceTypeIsAbstract = referenceType->referenceTypeNode.isAbstract;
42341 UA_NODESTORE_RELEASE(server, referenceType);
42342 if(referenceTypeIsAbstract == true) {
42343 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42344 msg: "Abstract reference type to the parent not allowed");
42345 return UA_STATUSCODE_BADREFERENCENOTALLOWED;
42346 }
42347
42348 /* Check hassubtype relation for type nodes */
42349 if(head->nodeClass == UA_NODECLASS_DATATYPE ||
42350 head->nodeClass == UA_NODECLASS_VARIABLETYPE ||
42351 head->nodeClass == UA_NODECLASS_OBJECTTYPE ||
42352 head->nodeClass == UA_NODECLASS_REFERENCETYPE) {
42353 /* Type needs hassubtype reference to the supertype */
42354 if(referenceType->referenceTypeNode.referenceTypeIndex !=
42355 UA_REFERENCETYPEINDEX_HASSUBTYPE) {
42356 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42357 msg: "Type nodes need to have a HasSubType reference to the parent");
42358 return UA_STATUSCODE_BADREFERENCENOTALLOWED;
42359 }
42360 /* Supertype needs to be of the same node type */
42361 if(parentNodeClass != head->nodeClass) {
42362 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42363 msg: "Type nodes needs to be of the same node "
42364 "type as their parent");
42365 return UA_STATUSCODE_BADPARENTNODEIDINVALID;
42366 }
42367 return UA_STATUSCODE_GOOD;
42368 }
42369
42370 /* Test if the referencetype is hierarchical */
42371 const UA_NodeId hierarchRefs = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
42372 if(!isNodeInTree_singleRef(server, leafNode: referenceTypeId, nodeToFind: &hierarchRefs,
42373 UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
42374 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42375 msg: "Reference type to the parent is not hierarchical");
42376 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
42377 }
42378
42379 return UA_STATUSCODE_GOOD;
42380}
42381
42382static UA_StatusCode
42383setDefaultValue(UA_Server *server, const UA_VariableNode *node) {
42384 /* Get the DataType */
42385 UA_StatusCode res = UA_STATUSCODE_GOOD;
42386 const UA_DataType *type = UA_Server_findDataType(server, typeId: &node->dataType);
42387 if(!type) {
42388 /* No description for the DataType found. It is possible that an
42389 * abstract DataType is used, e.g. UInteger. Browse to see if there is a
42390 * non-abstract subtype that can be used for the default value.
42391 *
42392 * Look up and downwards in the hierarchy. Some data types (e.g.
42393 * UtcTime) are derived from a non-abstract data type. This is then used
42394 * for the actual value, Use the first match. */
42395 UA_ReferenceTypeSet refs = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
42396 UA_ExpandedNodeId *typeCandidates = NULL;
42397 size_t typeCandidatesSize = 0;
42398 res = browseRecursive(server, startNodesSize: 1, startNodes: &node->dataType,
42399 browseDirection: UA_BROWSEDIRECTION_BOTH, refTypes: &refs,
42400 nodeClassMask: UA_NODECLASS_DATATYPE, false,
42401 resultsSize: &typeCandidatesSize, results: &typeCandidates);
42402 if(res != UA_STATUSCODE_GOOD)
42403 return res;
42404
42405 for(size_t i = 0; i < typeCandidatesSize; i++) {
42406 /* Skip BaseDataType (Variant). This is the root of the DataType
42407 * hierarchy. Variables of BaseDataType can be empty. */
42408 if(UA_NodeId_equal(n1: &UA_TYPES[UA_TYPES_VARIANT].typeId,
42409 n2: &typeCandidates[i].nodeId))
42410 continue;
42411 type = UA_Server_findDataType(server, typeId: &typeCandidates[i].nodeId);
42412 if(type)
42413 break;
42414 }
42415
42416 UA_Array_delete(p: typeCandidates, size: typeCandidatesSize,
42417 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
42418 if(!type)
42419 return UA_STATUSCODE_BADTYPEMISMATCH;
42420 }
42421
42422 /* Set up the value with the default content */
42423 UA_Variant val;
42424 UA_Variant_init(p: &val);
42425 if(node->valueRank < 0) {
42426 /* Set a scalar */
42427 void *data = UA_new(type);
42428 if(!data)
42429 return UA_STATUSCODE_BADOUTOFMEMORY;
42430 UA_Variant_setScalar(v: &val, p: data, type);
42431 } else if(node->valueRank == 0) {
42432 /* Use an empty array of one dimension */
42433 UA_Variant_setArray(v: &val, NULL, arraySize: 0, type);
42434 } else {
42435 /* Write an array that matches the ArrayDimensions */
42436 res = UA_Array_copy(src: node->arrayDimensions, size: node->arrayDimensionsSize,
42437 dst: (void**)&val.arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]);
42438 if(res != UA_STATUSCODE_GOOD)
42439 return res;
42440 val.arrayDimensionsSize = node->arrayDimensionsSize;
42441
42442 /* No length restriction in the ArrayDimension -> use length 1 */
42443 size_t size = 1;
42444 for(size_t i = 0; i < val.arrayDimensionsSize; i++) {
42445 if(val.arrayDimensions[i] == 0)
42446 val.arrayDimensions[i] = 1;
42447 size *= val.arrayDimensions[i];
42448 }
42449
42450 /* Create the content array */
42451 void *data = UA_Array_new(size, type);
42452 if(!data) {
42453 UA_Variant_clear(p: &val);
42454 return UA_STATUSCODE_BADOUTOFMEMORY;
42455 }
42456
42457 val.data = data;
42458 val.arrayLength = size;
42459 val.type = type;
42460 }
42461
42462 /* Write the value */
42463 res = writeAttribute(server, session: &server->adminSession, nodeId: &node->head.nodeId,
42464 attributeId: UA_ATTRIBUTEID_VALUE, attr: &val, attr_type: &UA_TYPES[UA_TYPES_VARIANT]);
42465
42466 /* Clean up */
42467 UA_Variant_clear(p: &val);
42468 return res;
42469}
42470
42471static UA_StatusCode
42472typeCheckVariableNode(UA_Server *server, UA_Session *session,
42473 const UA_VariableNode *node,
42474 const UA_VariableTypeNode *vt) {
42475 /* Check the datatype against the vt */
42476 if(!compatibleDataTypes(server, dataType: &node->dataType, constraintDataType: &vt->dataType)) {
42477 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42478 msg: "The value of is incompatible with "
42479 "the datatype of the VariableType");
42480 return UA_STATUSCODE_BADTYPEMISMATCH;
42481 }
42482
42483 /* Check valueRank against array dimensions */
42484 if(!compatibleValueRankArrayDimensions(server, session, valueRank: node->valueRank,
42485 arrayDimensionsSize: node->arrayDimensionsSize)) {
42486 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42487 msg: "The value rank of is incompatible with its array dimensions");
42488 return UA_STATUSCODE_BADTYPEMISMATCH;
42489 }
42490
42491 /* Check valueRank against the vt */
42492 if(!compatibleValueRanks(valueRank: node->valueRank, constraintValueRank: vt->valueRank)) {
42493 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42494 msg: "The value rank is incompatible "
42495 "with the value rank of the VariableType");
42496 return UA_STATUSCODE_BADTYPEMISMATCH;
42497 }
42498
42499 /* Check array dimensions against the vt */
42500 if(!compatibleArrayDimensions(constraintArrayDimensionsSize: vt->arrayDimensionsSize, constraintArrayDimensions: vt->arrayDimensions,
42501 testArrayDimensionsSize: node->arrayDimensionsSize, testArrayDimensions: node->arrayDimensions)) {
42502 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42503 msg: "The array dimensions are incompatible with the "
42504 "array dimensions of the VariableType");
42505 return UA_STATUSCODE_BADTYPEMISMATCH;
42506 }
42507
42508 /* Typecheck the value */
42509
42510 /* The value might come from a datasource, so we perform a
42511 * regular read. */
42512 UA_DataValue value;
42513 UA_DataValue_init(p: &value);
42514 UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value);
42515 if(retval != UA_STATUSCODE_GOOD)
42516 return retval;
42517
42518 /* Only BaseDataType (Variant) can have empty values. Create default content
42519 * otherwise that matches the constraints. */
42520 if(!value.hasValue || !value.value.type) {
42521 if(!UA_NodeId_equal(n1: &node->dataType, n2: &UA_TYPES[UA_TYPES_VARIANT].typeId)) {
42522 /* Warn if that is configured */
42523 if(!server->bootstrapNS0 &&
42524 server->config.allowEmptyVariables != UA_RULEHANDLING_ACCEPT)
42525 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42526 msg: "The value is empty. But this is only allowed for BaseDataType. "
42527 "Create a matching default value.");
42528
42529 /* Abort if that is configured */
42530 if(server->config.allowEmptyVariables == UA_RULEHANDLING_ABORT)
42531 retval = UA_STATUSCODE_BADTYPEMISMATCH;
42532
42533 /* Try to generate a default value if that is configured */
42534 if(server->config.allowEmptyVariables == UA_RULEHANDLING_DEFAULT) {
42535 retval = setDefaultValue(server, node);
42536 if(retval != UA_STATUSCODE_GOOD) {
42537 UA_LOG_NODEID_INFO(&node->head.nodeId,
42538 UA_LOG_INFO_SESSION(&server->config.logger, session,
42539 "AddNode (%.*s): Could not create a default value "
42540 "with StatusCode %s", (int)nodeIdStr.length,
42541 nodeIdStr.data, UA_StatusCode_name(retval)));
42542 }
42543
42544 /* Reread the current value for compat tests below */
42545 UA_DataValue_clear(p: &value);
42546 retval = readValueAttribute(server, session, vn: node, v: &value);
42547 }
42548 }
42549
42550 if(retval != UA_STATUSCODE_GOOD) {
42551 UA_DataValue_clear(p: &value);
42552 return retval;
42553 }
42554 }
42555
42556 /* Perform the value typecheck. If this fails, write the current value
42557 * again. The write-service tries to convert to the correct type... */
42558 const char *reason;
42559 if(!compatibleValue(server, session, targetDataTypeId: &node->dataType, targetValueRank: node->valueRank,
42560 targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions,
42561 value: &value.value, NULL, reason: &reason)) {
42562 retval = writeValueAttribute(server, session, nodeId: &node->head.nodeId, value: &value.value);
42563 if(retval != UA_STATUSCODE_GOOD) {
42564 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42565 msg: "The value is incompatible with the variable definition");
42566 }
42567 }
42568
42569 UA_DataValue_clear(p: &value);
42570 return retval;
42571}
42572
42573/********************/
42574/* Instantiate Node */
42575/********************/
42576
42577static const UA_NodeId baseDataVariableType =
42578 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_BASEDATAVARIABLETYPE}};
42579static const UA_NodeId baseObjectType =
42580 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_BASEOBJECTTYPE}};
42581static const UA_NodeId hasTypeDefinition =
42582 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASTYPEDEFINITION}};
42583
42584/* Use attributes from the variable type wherever required. Reload the node if
42585 * changes were made. */
42586static UA_StatusCode
42587useVariableTypeAttributes(UA_Server *server, UA_Session *session,
42588 const UA_VariableNode *node,
42589 const UA_VariableTypeNode *vt) {
42590 /* If no value is set, see if the vt provides one and copy it. This needs to
42591 * be done before copying the datatype from the vt, as setting the datatype
42592 * triggers a typecheck. */
42593 UA_Variant orig;
42594 UA_StatusCode retval =
42595 readWithReadValue(server, nodeId: &node->head.nodeId, attributeId: UA_ATTRIBUTEID_VALUE, v: &orig);
42596 if(retval != UA_STATUSCODE_GOOD)
42597 return retval;
42598
42599 if(orig.type) {
42600 /* A value is present */
42601 UA_Variant_clear(p: &orig);
42602 } else {
42603 UA_DataValue v;
42604 UA_DataValue_init(p: &v);
42605 retval = readValueAttribute(server, session, vn: (const UA_VariableNode*)vt, v: &v);
42606 if(retval == UA_STATUSCODE_GOOD && v.hasValue) {
42607 retval = writeValueAttribute(server, session, nodeId: &node->head.nodeId, value: &v.value);
42608 }
42609 UA_DataValue_clear(p: &v);
42610
42611 if(retval != UA_STATUSCODE_GOOD) {
42612 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42613 msg: "The default content of the VariableType could "
42614 "not be used. This may happen if the VariableNode "
42615 "makes additional restrictions.");
42616 retval = UA_STATUSCODE_GOOD;
42617 }
42618 }
42619
42620 /* If no datatype is given, use the datatype of the vt */
42621 if(UA_NodeId_isNull(p: &node->dataType)) {
42622 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42623 msg: "No datatype given; Copy the datatype attribute "
42624 "from the TypeDefinition");
42625 retval = writeAttribute(server, session, nodeId: &node->head.nodeId,
42626 attributeId: UA_ATTRIBUTEID_DATATYPE, attr: &vt->dataType,
42627 attr_type: &UA_TYPES[UA_TYPES_NODEID]);
42628 if(retval != UA_STATUSCODE_GOOD)
42629 return retval;
42630 }
42631
42632 /* Use the ArrayDimensions of the vt */
42633 if(node->arrayDimensionsSize == 0 && vt->arrayDimensionsSize > 0) {
42634 UA_Variant v;
42635 UA_Variant_init(p: &v);
42636 UA_Variant_setArray(v: &v, array: vt->arrayDimensions, arraySize: vt->arrayDimensionsSize,
42637 type: &UA_TYPES[UA_TYPES_UINT32]);
42638 retval = writeAttribute(server, session, nodeId: &node->head.nodeId,
42639 attributeId: UA_ATTRIBUTEID_ARRAYDIMENSIONS, attr: &v,
42640 attr_type: &UA_TYPES[UA_TYPES_VARIANT]);
42641 }
42642
42643 return retval;
42644}
42645
42646/* Search for an instance of "browseName" in node searchInstance. Used during
42647 * copyChildNodes to find overwritable/mergable nodes. Does not touch
42648 * outInstanceNodeId if no child is found. */
42649static UA_StatusCode
42650findChildByBrowsename(UA_Server *server, UA_Session *session,
42651 const UA_NodeId *searchInstance,
42652 const UA_QualifiedName *browseName,
42653 UA_NodeId *outInstanceNodeId) {
42654 UA_BrowseDescription bd;
42655 UA_BrowseDescription_init(p: &bd);
42656 bd.nodeId = *searchInstance;
42657 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES);
42658 bd.includeSubtypes = true;
42659 bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
42660 bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
42661 bd.resultMask = UA_BROWSERESULTMASK_BROWSENAME;
42662
42663 UA_BrowseResult br;
42664 UA_BrowseResult_init(p: &br);
42665 UA_UInt32 maxrefs = 0;
42666 Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br);
42667 if(br.statusCode != UA_STATUSCODE_GOOD)
42668 return br.statusCode;
42669
42670 UA_StatusCode retval = UA_STATUSCODE_GOOD;
42671 for(size_t i = 0; i < br.referencesSize; ++i) {
42672 UA_ReferenceDescription *rd = &br.references[i];
42673 if(rd->browseName.namespaceIndex == browseName->namespaceIndex &&
42674 UA_String_equal(s1: &rd->browseName.name, s2: &browseName->name)) {
42675 retval = UA_NodeId_copy(src: &rd->nodeId.nodeId, dst: outInstanceNodeId);
42676 break;
42677 }
42678 }
42679
42680 UA_BrowseResult_clear(p: &br);
42681 return retval;
42682}
42683
42684static const UA_NodeId mandatoryId =
42685 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_MODELLINGRULE_MANDATORY}};
42686
42687static UA_Boolean
42688isMandatoryChild(UA_Server *server, UA_Session *session,
42689 const UA_NodeId *childNodeId) {
42690 /* Get the child */
42691 const UA_Node *child = UA_NODESTORE_GET(server, childNodeId);
42692 if(!child)
42693 return false;
42694
42695 /* Look for the reference making the child mandatory */
42696 UA_NodePointer mandatoryP = UA_NodePointer_fromNodeId(id: &mandatoryId);
42697 for(size_t i = 0; i < child->head.referencesSize; ++i) {
42698 UA_NodeReferenceKind *rk = &child->head.references[i];
42699 if(rk->referenceTypeIndex != UA_REFERENCETYPEINDEX_HASMODELLINGRULE)
42700 continue;
42701 if(rk->isInverse)
42702 continue;
42703
42704 const UA_ReferenceTarget *t = NULL;
42705 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
42706 if(UA_NodePointer_equal(p1: mandatoryP, p2: t->targetId)) {
42707 UA_NODESTORE_RELEASE(server, child);
42708 return true;
42709 }
42710 }
42711 }
42712
42713 UA_NODESTORE_RELEASE(server, child);
42714 return false;
42715}
42716
42717static UA_StatusCode
42718copyAllChildren(UA_Server *server, UA_Session *session,
42719 const UA_NodeId *source, const UA_NodeId *destination);
42720
42721static void
42722Operation_addReference(UA_Server *server, UA_Session *session, void *context,
42723 const UA_AddReferencesItem *item, UA_StatusCode *retval);
42724
42725UA_StatusCode
42726addRef(UA_Server *server, UA_Session *session, const UA_NodeId *sourceId,
42727 const UA_NodeId *referenceTypeId, const UA_NodeId *targetId,
42728 UA_Boolean forward) {
42729 UA_AddReferencesItem ref_item;
42730 UA_AddReferencesItem_init(p: &ref_item);
42731 ref_item.sourceNodeId = *sourceId;
42732 ref_item.referenceTypeId = *referenceTypeId;
42733 ref_item.isForward = forward;
42734 ref_item.targetNodeId.nodeId = *targetId;
42735
42736 UA_StatusCode retval = UA_STATUSCODE_GOOD;
42737 Operation_addReference(server, session, NULL, item: &ref_item, retval: &retval);
42738 return retval;
42739}
42740
42741static UA_StatusCode
42742addInterfaceChildren(UA_Server *server, UA_Session *session,
42743 const UA_NodeId *nodeId, const UA_NodeId *typeId) {
42744 /* Get the hierarchy of the type and all its supertypes */
42745 UA_NodeId *hierarchy = NULL;
42746 size_t hierarchySize = 0;
42747 UA_StatusCode retval = getAllInterfaceChildNodeIds(server, objectNode: nodeId, objectTypeNode: typeId,
42748 interfaceChildNodes: &hierarchy, interfaceChildNodesSize: &hierarchySize);
42749 if(retval != UA_STATUSCODE_GOOD)
42750 return retval;
42751
42752 /* Copy members of the type and supertypes (and instantiate them) */
42753 for(size_t i = 0; i < hierarchySize; ++i) {
42754 retval = copyAllChildren(server, session, source: &hierarchy[i], destination: nodeId);
42755 if(retval != UA_STATUSCODE_GOOD) {
42756 UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]);
42757 return retval;
42758 }
42759 }
42760
42761 for(size_t i = 0; i < hierarchySize; ++i) {
42762 UA_NodeId refId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASINTERFACE);
42763 retval = addRef(server, session: &server->adminSession, sourceId: nodeId, referenceTypeId: &refId, targetId: &hierarchy[i], true);
42764
42765 /* Don't add the original HasInterface reference to ObjectType sub nodes */
42766 if(retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
42767 retval = UA_STATUSCODE_GOOD;
42768 } else if(retval != UA_STATUSCODE_GOOD) {
42769 break;
42770 }
42771 }
42772
42773 UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]);
42774 return retval;
42775}
42776
42777static UA_StatusCode
42778copyChild(UA_Server *server, UA_Session *session,
42779 const UA_NodeId *destinationNodeId,
42780 const UA_ReferenceDescription *rd) {
42781 UA_assert(session);
42782
42783 /* Is there an existing child with the browsename? */
42784 UA_NodeId existingChild = UA_NODEID_NULL;
42785 UA_StatusCode retval = findChildByBrowsename(server, session, searchInstance: destinationNodeId,
42786 browseName: &rd->browseName, outInstanceNodeId: &existingChild);
42787 if(retval != UA_STATUSCODE_GOOD)
42788 return retval;
42789
42790 /* Have a child with that browseName. Deep-copy missing members. */
42791 if(!UA_NodeId_isNull(p: &existingChild)) {
42792 if(rd->nodeClass == UA_NODECLASS_VARIABLE ||
42793 rd->nodeClass == UA_NODECLASS_OBJECT)
42794 retval = copyAllChildren(server, session, source: &rd->nodeId.nodeId, destination: &existingChild);
42795 UA_NodeId_clear(p: &existingChild);
42796 return retval;
42797 }
42798
42799 /* Is the child mandatory? If not, ask callback whether child should be instantiated.
42800 * If not, skip. */
42801 if(!isMandatoryChild(server, session, childNodeId: &rd->nodeId.nodeId)) {
42802 if(!server->config.nodeLifecycle.createOptionalChild)
42803 return UA_STATUSCODE_GOOD;
42804 UA_UNLOCK(&server->serviceMutex);
42805 UA_Boolean createChild = server->config.nodeLifecycle.
42806 createOptionalChild(server, &session->sessionId, session->sessionHandle,
42807 &rd->nodeId.nodeId, destinationNodeId, &rd->referenceTypeId);
42808 UA_LOCK(&server->serviceMutex);
42809 if(!createChild)
42810 return UA_STATUSCODE_GOOD;
42811 }
42812
42813 /* Child is a method -> create a reference */
42814 if(rd->nodeClass == UA_NODECLASS_METHOD) {
42815 UA_AddReferencesItem newItem;
42816 UA_AddReferencesItem_init(p: &newItem);
42817 newItem.sourceNodeId = *destinationNodeId;
42818 newItem.referenceTypeId = rd->referenceTypeId;
42819 newItem.isForward = true;
42820 newItem.targetNodeId = rd->nodeId;
42821 newItem.targetNodeClass = UA_NODECLASS_METHOD;
42822 Operation_addReference(server, session, NULL, item: &newItem, retval: &retval);
42823 return retval;
42824 }
42825
42826 /* Child is a variable or object */
42827 if(rd->nodeClass == UA_NODECLASS_VARIABLE ||
42828 rd->nodeClass == UA_NODECLASS_OBJECT) {
42829 /* Make a copy of the node */
42830 UA_Node *node;
42831 retval = UA_NODESTORE_GETCOPY(server, &rd->nodeId.nodeId, &node);
42832 if(retval != UA_STATUSCODE_GOOD)
42833 return retval;
42834
42835 /* Remove the context of the copied node */
42836 node->head.context = NULL;
42837 node->head.constructed = false;
42838#ifdef UA_ENABLE_SUBSCRIPTIONS
42839 node->head.monitoredItems = NULL;
42840#endif
42841
42842 /* Reset the NodeId (random numeric id will be assigned in the nodestore) */
42843 UA_NodeId_clear(p: &node->head.nodeId);
42844 node->head.nodeId.namespaceIndex = destinationNodeId->namespaceIndex;
42845
42846 if(server->config.nodeLifecycle.generateChildNodeId) {
42847 UA_UNLOCK(&server->serviceMutex);
42848 retval = server->config.nodeLifecycle.
42849 generateChildNodeId(server, &session->sessionId, session->sessionHandle,
42850 &rd->nodeId.nodeId, destinationNodeId,
42851 &rd->referenceTypeId, &node->head.nodeId);
42852 UA_LOCK(&server->serviceMutex);
42853 if(retval != UA_STATUSCODE_GOOD) {
42854 UA_NODESTORE_DELETE(server, node);
42855 return retval;
42856 }
42857 }
42858
42859 /* Remove references, they are re-created from scratch in addnode_finish */
42860 /* TODO: Be more clever in removing references that are re-added during
42861 * addnode_finish. That way, we can call addnode_finish also on children that were
42862 * manually added by the user during addnode_begin and addnode_finish. */
42863 /* For now we keep all the modelling rule references and delete all others */
42864 const UA_NodeId nodeId_typesFolder= UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_TYPESFOLDER);
42865 const UA_ReferenceTypeSet reftypes_aggregates =
42866 UA_REFTYPESET(UA_REFERENCETYPEINDEX_AGGREGATES);
42867 UA_ReferenceTypeSet reftypes_skipped;
42868 /* Check if the hasModellingRule-reference is required (configured or node in an
42869 instance declaration) */
42870 if(server->config.modellingRulesOnInstances ||
42871 isNodeInTree(server, leafNode: destinationNodeId,
42872 nodeToFind: &nodeId_typesFolder, relevantRefs: &reftypes_aggregates)) {
42873 reftypes_skipped = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASMODELLINGRULE);
42874 } else {
42875 UA_ReferenceTypeSet_init(set: &reftypes_skipped);
42876 }
42877 reftypes_skipped = UA_ReferenceTypeSet_union(setA: reftypes_skipped, setB: UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE));
42878 UA_Node_deleteReferencesSubset(node, keepSet: &reftypes_skipped);
42879
42880 /* Add the node to the nodestore */
42881 UA_NodeId newNodeId;
42882 retval = UA_NODESTORE_INSERT(server, node, &newNodeId);
42883 /* node = NULL; The pointer is no longer valid */
42884 if(retval != UA_STATUSCODE_GOOD)
42885 return retval;
42886
42887 /* Add the node references */
42888 retval = AddNode_addRefs(server, session, nodeId: &newNodeId, parentNodeId: destinationNodeId,
42889 referenceTypeId: &rd->referenceTypeId, typeDefinitionId: &rd->typeDefinition.nodeId);
42890 if(retval != UA_STATUSCODE_GOOD) {
42891 UA_NODESTORE_REMOVE(server, &newNodeId);
42892 UA_NodeId_clear(p: &newNodeId);
42893 return retval;
42894 }
42895
42896 if (rd->nodeClass == UA_NODECLASS_VARIABLE) {
42897 retval = checkSetIsDynamicVariable(server, session, nodeId: &newNodeId);
42898
42899 if(retval != UA_STATUSCODE_GOOD) {
42900 UA_NODESTORE_REMOVE(server, &newNodeId);
42901 return retval;
42902 }
42903 }
42904
42905 /* For the new child, recursively copy the members of the original. No
42906 * typechecking is performed here. Assuming that the original is
42907 * consistent. */
42908 retval = copyAllChildren(server, session, source: &rd->nodeId.nodeId, destination: &newNodeId);
42909 if(retval != UA_STATUSCODE_GOOD) {
42910 deleteNode(server, nodeId: newNodeId, true);
42911 return retval;
42912 }
42913
42914 /* Check if its a dynamic variable, add all type and/or interface
42915 * children and call the constructor */
42916 retval = AddNode_finish(server, session, nodeId: &newNodeId);
42917 if(retval != UA_STATUSCODE_GOOD) {
42918 deleteNode(server, nodeId: newNodeId, true);
42919 return retval;
42920 }
42921
42922 /* Clean up. Because it can happen that a string is assigned as ID at
42923 * generateChildNodeId. */
42924 UA_NodeId_clear(p: &newNodeId);
42925 }
42926
42927 return retval;
42928}
42929
42930/* Copy any children of Node sourceNodeId to another node destinationNodeId. */
42931static UA_StatusCode
42932copyAllChildren(UA_Server *server, UA_Session *session,
42933 const UA_NodeId *source, const UA_NodeId *destination) {
42934 /* Browse to get all children of the source */
42935 UA_BrowseDescription bd;
42936 UA_BrowseDescription_init(p: &bd);
42937 bd.nodeId = *source;
42938 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES);
42939 bd.includeSubtypes = true;
42940 bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
42941 bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
42942 bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS |
42943 UA_BROWSERESULTMASK_BROWSENAME | UA_BROWSERESULTMASK_TYPEDEFINITION;
42944
42945 UA_BrowseResult br;
42946 UA_BrowseResult_init(p: &br);
42947 UA_UInt32 maxrefs = 0;
42948 Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br);
42949 if(br.statusCode != UA_STATUSCODE_GOOD)
42950 return br.statusCode;
42951
42952 UA_StatusCode retval = UA_STATUSCODE_GOOD;
42953 for(size_t i = 0; i < br.referencesSize; ++i) {
42954 UA_ReferenceDescription *rd = &br.references[i];
42955 retval = copyChild(server, session, destinationNodeId: destination, rd);
42956 if(retval != UA_STATUSCODE_GOOD)
42957 break;
42958 }
42959
42960 UA_BrowseResult_clear(p: &br);
42961 return retval;
42962}
42963
42964static UA_StatusCode
42965addTypeChildren(UA_Server *server, UA_Session *session,
42966 const UA_NodeId *nodeId, const UA_NodeId *typeId) {
42967 /* Get the hierarchy of the type and all its supertypes */
42968 UA_NodeId *hierarchy = NULL;
42969 size_t hierarchySize = 0;
42970 UA_StatusCode retval = getParentTypeAndInterfaceHierarchy(server, typeNode: typeId,
42971 typeHierarchy: &hierarchy, typeHierarchySize: &hierarchySize);
42972 if(retval != UA_STATUSCODE_GOOD)
42973 return retval;
42974 UA_assert(hierarchySize < 1000);
42975
42976 /* Copy members of the type and supertypes (and instantiate them) */
42977 for(size_t i = 0; i < hierarchySize; ++i) {
42978 retval = copyAllChildren(server, session, source: &hierarchy[i], destination: nodeId);
42979 if(retval != UA_STATUSCODE_GOOD)
42980 break;
42981 }
42982
42983 UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]);
42984 return retval;
42985}
42986
42987/************/
42988/* Add Node */
42989/************/
42990
42991static const UA_NodeId hasSubtype = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}};
42992
42993UA_StatusCode
42994AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
42995 const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
42996 const UA_NodeId *typeDefinitionId) {
42997 /* Get the node */
42998 const UA_Node *type = NULL;
42999 const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
43000 if(!node)
43001 return UA_STATUSCODE_BADNODEIDUNKNOWN;
43002
43003 /* Use the typeDefinition as parent for type-nodes */
43004 const UA_NodeHead *head = &node->head;
43005 if(head->nodeClass == UA_NODECLASS_VARIABLETYPE ||
43006 head->nodeClass == UA_NODECLASS_OBJECTTYPE ||
43007 head->nodeClass == UA_NODECLASS_REFERENCETYPE ||
43008 head->nodeClass == UA_NODECLASS_DATATYPE) {
43009 if(UA_NodeId_equal(n1: referenceTypeId, n2: &UA_NODEID_NULL))
43010 referenceTypeId = &hasSubtype;
43011 const UA_Node *parentNode = UA_NODESTORE_GET(server, parentNodeId);
43012 if(parentNode) {
43013 if(parentNode->head.nodeClass == head->nodeClass)
43014 typeDefinitionId = parentNodeId;
43015 UA_NODESTORE_RELEASE(server, parentNode);
43016 }
43017 }
43018
43019 UA_StatusCode retval;
43020 /* Make sure newly created node does not have itself as parent */
43021 if(UA_NodeId_equal(n1: nodeId, n2: parentNodeId)) {
43022 logAddNode(logger: &server->config.logger, session, nodeId,
43023 msg: "A node cannot have itself as parent");
43024 retval = UA_STATUSCODE_BADINVALIDARGUMENT;
43025 goto cleanup;
43026 }
43027
43028
43029 /* Check parent reference. Objects may have no parent. */
43030 retval = checkParentReference(server, session, head, parentNodeId, referenceTypeId);
43031 if(retval != UA_STATUSCODE_GOOD) {
43032 logAddNode(logger: &server->config.logger, session, nodeId,
43033 msg: "The parent reference for is invalid");
43034 goto cleanup;
43035 }
43036
43037 /* Replace empty typeDefinition with the most permissive default */
43038 if((head->nodeClass == UA_NODECLASS_VARIABLE ||
43039 head->nodeClass == UA_NODECLASS_OBJECT) &&
43040 UA_NodeId_isNull(p: typeDefinitionId)) {
43041 logAddNode(logger: &server->config.logger, session, nodeId,
43042 msg: "No TypeDefinition. Use the default "
43043 "TypeDefinition for the Variable/Object");
43044 if(head->nodeClass == UA_NODECLASS_VARIABLE)
43045 typeDefinitionId = &baseDataVariableType;
43046 else
43047 typeDefinitionId = &baseObjectType;
43048 }
43049
43050 /* Get the node type. There must be a typedefinition for variables, objects
43051 * and type-nodes. See the above checks. */
43052 if(!UA_NodeId_isNull(p: typeDefinitionId)) {
43053 /* Get the type node */
43054 type = UA_NODESTORE_GET(server, typeDefinitionId);
43055 if(!type) {
43056 logAddNode(logger: &server->config.logger, session, nodeId, msg: "Node type not found");
43057 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43058 goto cleanup;
43059 }
43060
43061 UA_Boolean typeOk = false;
43062 const UA_NodeHead *typeHead = &type->head;
43063 switch(head->nodeClass) {
43064 case UA_NODECLASS_DATATYPE:
43065 typeOk = typeHead->nodeClass == UA_NODECLASS_DATATYPE;
43066 break;
43067 case UA_NODECLASS_METHOD:
43068 typeOk = typeHead->nodeClass == UA_NODECLASS_METHOD;
43069 break;
43070 case UA_NODECLASS_OBJECT:
43071 case UA_NODECLASS_OBJECTTYPE:
43072 typeOk = typeHead->nodeClass == UA_NODECLASS_OBJECTTYPE;
43073 break;
43074 case UA_NODECLASS_REFERENCETYPE:
43075 typeOk = typeHead->nodeClass == UA_NODECLASS_REFERENCETYPE;
43076 break;
43077 case UA_NODECLASS_VARIABLE:
43078 case UA_NODECLASS_VARIABLETYPE:
43079 typeOk = typeHead->nodeClass == UA_NODECLASS_VARIABLETYPE;
43080 break;
43081 case UA_NODECLASS_VIEW:
43082 typeOk = typeHead->nodeClass == UA_NODECLASS_VIEW;
43083 break;
43084 default:
43085 typeOk = false;
43086 }
43087 if(!typeOk) {
43088 logAddNode(logger: &server->config.logger, session, nodeId,
43089 msg: "Type does not match the NodeClass");
43090 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43091 goto cleanup;
43092 }
43093
43094 /* See if the type has the correct node class. For type-nodes, we know
43095 * that type has the same nodeClass from checkParentReference. */
43096 if(head->nodeClass == UA_NODECLASS_VARIABLE &&
43097 type->variableTypeNode.isAbstract) {
43098 /* Get subtypes of the parent reference types */
43099 UA_ReferenceTypeSet refTypes1, refTypes2;
43100 retval |= referenceTypeIndices(server, refType: &parentReferences[0], indices: &refTypes1, true);
43101 retval |= referenceTypeIndices(server, refType: &parentReferences[1], indices: &refTypes2, true);
43102 UA_ReferenceTypeSet refTypes = UA_ReferenceTypeSet_union(setA: refTypes1, setB: refTypes2);
43103 if(retval != UA_STATUSCODE_GOOD)
43104 goto cleanup;
43105
43106 /* Abstract variable is allowed if parent is a children of a
43107 * base data variable. An abstract variable may be part of an
43108 * object type which again is below BaseObjectType */
43109 const UA_NodeId variableTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATAVARIABLETYPE);
43110 const UA_NodeId objectTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE);
43111 if(!isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &variableTypes, relevantRefs: &refTypes) &&
43112 !isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &objectTypes, relevantRefs: &refTypes)) {
43113 logAddNode(logger: &server->config.logger, session, nodeId,
43114 msg: "Type of variable node must be a "
43115 "VariableType and not cannot be abstract");
43116 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43117 goto cleanup;
43118 }
43119 }
43120
43121 if(head->nodeClass == UA_NODECLASS_OBJECT &&
43122 type->objectTypeNode.isAbstract) {
43123 /* Get subtypes of the parent reference types */
43124 UA_ReferenceTypeSet refTypes1, refTypes2;
43125 retval |= referenceTypeIndices(server, refType: &parentReferences[0], indices: &refTypes1, true);
43126 retval |= referenceTypeIndices(server, refType: &parentReferences[1], indices: &refTypes2, true);
43127 UA_ReferenceTypeSet refTypes = UA_ReferenceTypeSet_union(setA: refTypes1, setB: refTypes2);
43128 if(retval != UA_STATUSCODE_GOOD)
43129 goto cleanup;
43130
43131
43132 /* Object node created of an abstract ObjectType. Only allowed if
43133 * within BaseObjectType folder or if it's an event (subType of
43134 * BaseEventType) */
43135 const UA_NodeId objectTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE);
43136 UA_Boolean isInBaseObjectType =
43137 isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &objectTypes, relevantRefs: &refTypes);
43138
43139 const UA_NodeId eventTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
43140 UA_Boolean isInBaseEventType =
43141 isNodeInTree_singleRef(server, leafNode: &type->head.nodeId, nodeToFind: &eventTypes,
43142 UA_REFERENCETYPEINDEX_HASSUBTYPE);
43143
43144 if(!isInBaseObjectType &&
43145 !(isInBaseEventType && UA_NodeId_isNull(p: parentNodeId))) {
43146 logAddNode(logger: &server->config.logger, session, nodeId,
43147 msg: "Type of ObjectNode must be ObjectType and not be abstract");
43148 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43149 goto cleanup;
43150 }
43151 }
43152 }
43153
43154 /* Add reference to the parent */
43155 if(!UA_NodeId_isNull(p: parentNodeId)) {
43156 if(UA_NodeId_isNull(p: referenceTypeId)) {
43157 logAddNode(logger: &server->config.logger, session, nodeId,
43158 msg: "Reference to parent cannot be null");
43159 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43160 goto cleanup;
43161 }
43162
43163 retval = addRef(server, session, sourceId: &head->nodeId, referenceTypeId,
43164 targetId: parentNodeId, false);
43165 if(retval != UA_STATUSCODE_GOOD) {
43166 logAddNode(logger: &server->config.logger, session, nodeId,
43167 msg: "Adding reference to parent failed");
43168 goto cleanup;
43169 }
43170 }
43171
43172 /* Add a hasTypeDefinition reference */
43173 if(head->nodeClass == UA_NODECLASS_VARIABLE ||
43174 head->nodeClass == UA_NODECLASS_OBJECT) {
43175 UA_assert(type != NULL); /* see above */
43176 retval = addRef(server, session, sourceId: &head->nodeId, referenceTypeId: &hasTypeDefinition,
43177 targetId: &type->head.nodeId, true);
43178 if(retval != UA_STATUSCODE_GOOD) {
43179 logAddNode(logger: &server->config.logger, session, nodeId,
43180 msg: "Adding a reference to the type definition failed");
43181 }
43182 }
43183
43184 cleanup:
43185 UA_NODESTORE_RELEASE(server, node);
43186 if(type)
43187 UA_NODESTORE_RELEASE(server, type);
43188 return retval;
43189}
43190
43191/* Create the node and add it to the nodestore. But don't typecheck and add
43192 * references so far */
43193UA_StatusCode
43194AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
43195 const UA_AddNodesItem *item, UA_NodeId *outNewNodeId) {
43196 /* Do not check access for server */
43197 if(session != &server->adminSession && server->config.accessControl.allowAddNode) {
43198 UA_UNLOCK(&server->serviceMutex);
43199 if(!server->config.accessControl.
43200 allowAddNode(server, &server->config.accessControl,
43201 &session->sessionId, session->sessionHandle, item)) {
43202 UA_LOCK(&server->serviceMutex);
43203 return UA_STATUSCODE_BADUSERACCESSDENIED;
43204 }
43205 UA_LOCK(&server->serviceMutex);
43206 }
43207
43208 /* Check the namespaceindex */
43209 if(item->requestedNewNodeId.nodeId.namespaceIndex >= server->namespacesSize) {
43210 UA_LOG_INFO_SESSION(&server->config.logger, session,
43211 "AddNode: Namespace invalid");
43212 return UA_STATUSCODE_BADNODEIDINVALID;
43213 }
43214
43215 if(item->nodeAttributes.encoding != UA_EXTENSIONOBJECT_DECODED &&
43216 item->nodeAttributes.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) {
43217 UA_LOG_INFO_SESSION(&server->config.logger, session,
43218 "AddNode: Node attributes invalid");
43219 return UA_STATUSCODE_BADINTERNALERROR;
43220 }
43221
43222 /* Create a node */
43223 UA_Node *node = UA_NODESTORE_NEW(server, item->nodeClass);
43224 if(!node) {
43225 UA_LOG_INFO_SESSION(&server->config.logger, session,
43226 "AddNode: Node could not create a node "
43227 "in the nodestore");
43228 return UA_STATUSCODE_BADOUTOFMEMORY;
43229 }
43230
43231 UA_NodeId tmpOutId = UA_NODEID_NULL;
43232 /* Fill the node attributes */
43233 node->head.context = nodeContext;
43234 UA_StatusCode retval =
43235 UA_NodeId_copy(src: &item->requestedNewNodeId.nodeId, dst: &node->head.nodeId);
43236 if(retval != UA_STATUSCODE_GOOD)
43237 goto create_error;
43238
43239 retval = UA_QualifiedName_copy(src: &item->browseName, dst: &node->head.browseName);
43240 if(retval != UA_STATUSCODE_GOOD)
43241 goto create_error;
43242
43243 retval = UA_Node_setAttributes(node, attributes: item->nodeAttributes.content.decoded.data,
43244 attributeType: item->nodeAttributes.content.decoded.type);
43245 if(retval != UA_STATUSCODE_GOOD)
43246 goto create_error;
43247
43248 /* Add the node to the nodestore */
43249 if(!outNewNodeId)
43250 outNewNodeId = &tmpOutId;
43251 retval = UA_NODESTORE_INSERT(server, node, outNewNodeId);
43252 if(retval != UA_STATUSCODE_GOOD) {
43253 UA_LOG_INFO_SESSION(&server->config.logger, session,
43254 "AddNode: Node could not add the new node "
43255 "to the nodestore with error code %s",
43256 UA_StatusCode_name(retval));
43257 return retval;
43258 }
43259
43260 if(outNewNodeId == &tmpOutId)
43261 UA_NodeId_clear(p: &tmpOutId);
43262
43263 return UA_STATUSCODE_GOOD;
43264
43265create_error:
43266 UA_LOG_INFO_SESSION(&server->config.logger, session,
43267 "AddNode: Node could not create a node "
43268 "with error code %s", UA_StatusCode_name(retval));
43269 UA_NODESTORE_DELETE(server, node);
43270 return retval;
43271}
43272
43273static UA_StatusCode
43274findDefaultInstanceBrowseNameNode(UA_Server *server, UA_NodeId startingNode,
43275 UA_NodeId *foundId) {
43276 UA_NodeId_init(p: foundId);
43277 UA_RelativePathElement rpe;
43278 UA_RelativePathElement_init(p: &rpe);
43279 rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
43280 rpe.targetName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "DefaultInstanceBrowseName");
43281 UA_BrowsePath bp;
43282 UA_BrowsePath_init(p: &bp);
43283 bp.startingNode = startingNode;
43284 bp.relativePath.elementsSize = 1;
43285 bp.relativePath.elements = &rpe;
43286 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp);
43287 UA_StatusCode retval = bpr.statusCode;
43288 if(retval == UA_STATUSCODE_GOOD && bpr.targetsSize > 0)
43289 retval = UA_NodeId_copy(src: &bpr.targets[0].targetId.nodeId, dst: foundId);
43290 UA_BrowsePathResult_clear(p: &bpr);
43291 return retval;
43292}
43293
43294/* Check if we got a valid browse name for the new node. For object nodes the
43295 * BrowseName may only be null if the parent type has a
43296 * 'DefaultInstanceBrowseName' property. */
43297static UA_StatusCode
43298checkSetBrowseName(UA_Server *server, UA_Session *session, UA_AddNodesItem *item) {
43299 /* If the object node already has a browse name we are done here. */
43300 if(!UA_QualifiedName_isNull(q: &item->browseName))
43301 return UA_STATUSCODE_GOOD;
43302
43303 /* Nodes other than Objects must have a BrowseName */
43304 if(item->nodeClass != UA_NODECLASS_OBJECT)
43305 return UA_STATUSCODE_BADBROWSENAMEINVALID;
43306
43307 /* At this point we have an object with an empty browse name. Check the type
43308 * node if it has a DefaultInstanceBrowseName property. */
43309 UA_NodeId defaultBrowseNameNode;
43310 UA_StatusCode retval =
43311 findDefaultInstanceBrowseNameNode(server, startingNode: item->typeDefinition.nodeId,
43312 foundId: &defaultBrowseNameNode);
43313 if(retval != UA_STATUSCODE_GOOD)
43314 return UA_STATUSCODE_BADBROWSENAMEINVALID;
43315
43316 UA_Variant defaultBrowseName;
43317 retval = readWithReadValue(server, nodeId: &defaultBrowseNameNode,
43318 attributeId: UA_ATTRIBUTEID_VALUE, v: &defaultBrowseName);
43319 UA_NodeId_clear(p: &defaultBrowseNameNode);
43320 if(retval != UA_STATUSCODE_GOOD)
43321 return UA_STATUSCODE_BADBROWSENAMEINVALID;
43322
43323 if(UA_Variant_hasScalarType(v: &defaultBrowseName, type: &UA_TYPES[UA_TYPES_QUALIFIEDNAME])) {
43324 item->browseName = *(UA_QualifiedName*)defaultBrowseName.data;
43325 UA_QualifiedName_init(p: (UA_QualifiedName*)defaultBrowseName.data);
43326 } else {
43327 retval = UA_STATUSCODE_BADBROWSENAMEINVALID;
43328 }
43329
43330 UA_Variant_clear(p: &defaultBrowseName);
43331 return retval;
43332}
43333
43334/* Prepare the node, then add it to the nodestore */
43335static UA_StatusCode
43336Operation_addNode_begin(UA_Server *server, UA_Session *session, void *nodeContext,
43337 const UA_AddNodesItem *item, const UA_NodeId *parentNodeId,
43338 const UA_NodeId *referenceTypeId, UA_NodeId *outNewNodeId) {
43339 /* Create a temporary NodeId if none is returned */
43340 UA_NodeId newId;
43341 if(!outNewNodeId) {
43342 UA_NodeId_init(p: &newId);
43343 outNewNodeId = &newId;
43344 }
43345
43346 /* Set the BrowsenName before adding to the Nodestore. The BrowseName is
43347 * immutable afterwards. */
43348 UA_Boolean noBrowseName = UA_QualifiedName_isNull(q: &item->browseName);
43349 UA_StatusCode retval =
43350 checkSetBrowseName(server, session, item: (UA_AddNodesItem*)(uintptr_t)item);
43351 if(retval != UA_STATUSCODE_GOOD)
43352 return retval;
43353
43354 /* Create the node and add it to the nodestore */
43355 retval = AddNode_raw(server, session, nodeContext, item, outNewNodeId);
43356 if(retval != UA_STATUSCODE_GOOD)
43357 goto cleanup;
43358
43359 /* Typecheck and add references to parent and type definition */
43360 retval = AddNode_addRefs(server, session, nodeId: outNewNodeId, parentNodeId,
43361 referenceTypeId, typeDefinitionId: &item->typeDefinition.nodeId);
43362 if(retval != UA_STATUSCODE_GOOD)
43363 deleteNode(server, nodeId: *outNewNodeId, true);
43364
43365 if(outNewNodeId == &newId)
43366 UA_NodeId_clear(p: &newId);
43367
43368 cleanup:
43369 if(noBrowseName)
43370 UA_QualifiedName_clear(p: (UA_QualifiedName*)(uintptr_t)&item->browseName);
43371 return retval;
43372}
43373
43374/* Construct children first */
43375static UA_StatusCode
43376recursiveCallConstructors(UA_Server *server, UA_Session *session,
43377 const UA_NodeId *nodeId, const UA_Node *type) {
43378 /* Browse the children */
43379 UA_BrowseDescription bd;
43380 UA_BrowseDescription_init(p: &bd);
43381 bd.nodeId = *nodeId;
43382 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES);
43383 bd.includeSubtypes = true;
43384 bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
43385
43386 UA_BrowseResult br;
43387 UA_BrowseResult_init(p: &br);
43388 UA_UInt32 maxrefs = 0;
43389 Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br);
43390 if(br.statusCode != UA_STATUSCODE_GOOD)
43391 return br.statusCode;
43392
43393 /* Call the constructor for every unconstructed child node */
43394 UA_StatusCode retval = UA_STATUSCODE_GOOD;
43395 for(size_t i = 0; i < br.referencesSize; ++i) {
43396 UA_ReferenceDescription *rd = &br.references[i];
43397 if(!UA_ExpandedNodeId_isLocal(n: &rd->nodeId))
43398 continue;
43399 const UA_Node *target = UA_NODESTORE_GET(server, &rd->nodeId.nodeId);
43400 if(!target)
43401 continue;
43402 if(target->head.constructed) {
43403 UA_NODESTORE_RELEASE(server, target);
43404 continue;
43405 }
43406
43407 const UA_Node *targetType = NULL;
43408 if(target->head.nodeClass == UA_NODECLASS_VARIABLE ||
43409 target->head.nodeClass == UA_NODECLASS_OBJECT) {
43410 targetType = getNodeType(server, head: &target->head);
43411 if(!targetType) {
43412 UA_NODESTORE_RELEASE(server, target);
43413 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43414 break;
43415 }
43416 }
43417
43418 UA_NODESTORE_RELEASE(server, target);
43419 retval = recursiveCallConstructors(server, session, nodeId: &rd->nodeId.nodeId, type: targetType);
43420
43421 if(targetType)
43422 UA_NODESTORE_RELEASE(server, targetType);
43423 if(retval != UA_STATUSCODE_GOOD)
43424 break;
43425 }
43426
43427 UA_BrowseResult_clear(p: &br);
43428
43429 /* If a child could not be constructed or the node is already constructed */
43430 if(retval != UA_STATUSCODE_GOOD)
43431 return retval;
43432
43433 /* Get the node context */
43434 const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
43435 if(!node)
43436 return UA_STATUSCODE_BADNODEIDUNKNOWN;
43437 void *context = node->head.context;
43438 UA_NODESTORE_RELEASE(server, node);
43439
43440 /* Call the global constructor */
43441 if(server->config.nodeLifecycle.constructor) {
43442 UA_UNLOCK(&server->serviceMutex);
43443 retval = server->config.nodeLifecycle.
43444 constructor(server, &session->sessionId,
43445 session->sessionHandle, nodeId, &context);
43446 UA_LOCK(&server->serviceMutex);
43447 if(retval != UA_STATUSCODE_GOOD)
43448 return retval;
43449 }
43450
43451 /* Call the local (per-type) constructor */
43452 const UA_NodeTypeLifecycle *lifecycle = NULL;
43453 if(type && node->head.nodeClass == UA_NODECLASS_OBJECT)
43454 lifecycle = &type->objectTypeNode.lifecycle;
43455 else if(type && node->head.nodeClass == UA_NODECLASS_VARIABLE)
43456 lifecycle = &type->variableTypeNode.lifecycle;
43457 if(lifecycle && lifecycle->constructor) {
43458 UA_UNLOCK(&server->serviceMutex);
43459 retval = lifecycle->constructor(server, &session->sessionId,
43460 session->sessionHandle, &type->head.nodeId,
43461 type->head.context, nodeId, &context);
43462 UA_LOCK(&server->serviceMutex);
43463 if(retval != UA_STATUSCODE_GOOD)
43464 goto global_destructor;
43465 }
43466
43467 /* Set the context *and* mark the node as constructed */
43468 retval = UA_Server_editNode(server, session: &server->adminSession, nodeId,
43469 callback: (UA_EditNodeCallback)setConstructedNodeContext, data: context);
43470 if(retval != UA_STATUSCODE_GOOD)
43471 goto local_destructor;
43472
43473 /* All good, return */
43474 return retval;
43475
43476 /* Fail. Call the destructors. */
43477 local_destructor:
43478 if(lifecycle && lifecycle->destructor) {
43479 UA_UNLOCK(&server->serviceMutex);
43480 lifecycle->destructor(server, &session->sessionId, session->sessionHandle,
43481 &type->head.nodeId, type->head.context, nodeId, &context);
43482 UA_LOCK(&server->serviceMutex);
43483 }
43484
43485 global_destructor:
43486 if(server->config.nodeLifecycle.destructor) {
43487 UA_UNLOCK(&server->serviceMutex);
43488 server->config.nodeLifecycle.destructor(server, &session->sessionId,
43489 session->sessionHandle,
43490 nodeId, context);
43491 UA_LOCK(&server->serviceMutex);
43492 }
43493 return retval;
43494}
43495
43496/* Add new ReferenceType to the subtypes bitfield */
43497static UA_StatusCode
43498addReferenceTypeSubtype(UA_Server *server, UA_Session *session,
43499 UA_Node *node, void *context) {
43500 node->referenceTypeNode.subTypes =
43501 UA_ReferenceTypeSet_union(setA: node->referenceTypeNode.subTypes,
43502 setB: *(UA_ReferenceTypeSet*)context);
43503 return UA_STATUSCODE_GOOD;
43504}
43505
43506static UA_StatusCode
43507setReferenceTypeSubtypes(UA_Server *server, const UA_ReferenceTypeNode *node) {
43508 /* Get the ReferenceTypes upwards in the hierarchy */
43509 size_t parentsSize = 0;
43510 UA_ExpandedNodeId *parents = NULL;
43511 UA_ReferenceTypeSet reftypes_subtype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
43512 UA_StatusCode res =
43513 browseRecursive(server, startNodesSize: 1, startNodes: &node->head.nodeId, browseDirection: UA_BROWSEDIRECTION_INVERSE,
43514 refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_UNSPECIFIED,
43515 false, resultsSize: &parentsSize, results: &parents);
43516 if(res != UA_STATUSCODE_GOOD)
43517 return res;
43518
43519 /* Add the ReferenceTypeIndex of this node */
43520 const UA_ReferenceTypeSet *newRefSet = &node->subTypes;
43521 for(size_t i = 0; i < parentsSize; i++) {
43522 UA_Server_editNode(server, session: &server->adminSession, nodeId: &parents[i].nodeId,
43523 callback: addReferenceTypeSubtype, data: (void*)(uintptr_t)newRefSet);
43524 }
43525
43526 UA_Array_delete(p: parents, size: parentsSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
43527 return UA_STATUSCODE_GOOD;
43528}
43529
43530static UA_StatusCode
43531setVariableNodeDynamic(UA_Server *server, UA_Session *session,
43532 UA_Node *node, const void *_) {
43533 (void)_; /* unused */
43534 if(node->head.nodeClass == UA_NODECLASS_VARIABLE)
43535 ((UA_VariableNode*)node)->isDynamic = true;
43536 return UA_STATUSCODE_GOOD;
43537}
43538
43539static UA_StatusCode
43540checkSetIsDynamicVariable(UA_Server *server, UA_Session *session,
43541 const UA_NodeId *nodeId) {
43542 /* Get all hierarchical reference types */
43543 UA_ReferenceTypeSet reftypes_hierarchical;
43544 UA_ReferenceTypeSet_init(set: &reftypes_hierarchical);
43545 UA_NodeId hierarchicalRefs = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
43546 UA_StatusCode res =
43547 referenceTypeIndices(server, refType: &hierarchicalRefs, indices: &reftypes_hierarchical, true);
43548 if(res != UA_STATUSCODE_GOOD)
43549 return res;
43550
43551 /* Is the variable under the server object? */
43552 UA_NodeId serverNodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER);
43553 if(isNodeInTree(server, leafNode: nodeId, nodeToFind: &serverNodeId, relevantRefs: &reftypes_hierarchical))
43554 return UA_STATUSCODE_GOOD;
43555
43556 /* Is the variable in the type hierarchy? */
43557 UA_NodeId typesNodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_TYPESFOLDER);
43558 if(isNodeInTree(server, leafNode: nodeId, nodeToFind: &typesNodeId, relevantRefs: &reftypes_hierarchical))
43559 return UA_STATUSCODE_GOOD;
43560
43561 /* Is the variable a property of a method node (InputArguments /
43562 * OutputArguments)? */
43563 UA_BrowseDescription bd;
43564 UA_BrowseDescription_init(p: &bd);
43565 bd.nodeId = *nodeId;
43566 bd.browseDirection = UA_BROWSEDIRECTION_INVERSE;
43567 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
43568 bd.includeSubtypes = false;
43569 bd.nodeClassMask = UA_NODECLASS_METHOD;
43570 UA_BrowseResult br;
43571 UA_BrowseResult_init(p: &br);
43572 UA_UInt32 maxrefs = 0;
43573 Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br);
43574 UA_Boolean hasParentMethod = (br.referencesSize > 0);
43575 UA_BrowseResult_clear(p: &br);
43576 if(hasParentMethod)
43577 return UA_STATUSCODE_GOOD;
43578
43579 /* Set the variable to "dynamic" */
43580 UA_Server_editNode(server, session, nodeId,
43581 callback: (UA_EditNodeCallback)setVariableNodeDynamic, NULL);
43582
43583 return UA_STATUSCODE_GOOD;
43584}
43585
43586/* Children, references, type-checking, constructors. */
43587UA_StatusCode
43588AddNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId) {
43589 /* Get the node */
43590 const UA_Node *type = NULL;
43591 const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
43592 if(!node)
43593 return UA_STATUSCODE_BADNODEIDUNKNOWN;
43594
43595 /* Set the ReferenceTypesSet of subtypes in the ReferenceTypeNode */
43596 UA_StatusCode retval = UA_STATUSCODE_GOOD;
43597 if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
43598 retval = setReferenceTypeSubtypes(server, node: &node->referenceTypeNode);
43599 if(retval != UA_STATUSCODE_GOOD)
43600 goto cleanup;
43601 }
43602
43603 /* Check NodeClass for 'hasSubtype'. UA_NODECLASS_VARIABLE not allowed
43604 * to have subtype */
43605 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
43606 for(size_t i = 0; i < node->head.referencesSize; i++) {
43607 if(node->head.references[i].referenceTypeIndex ==
43608 UA_REFERENCETYPEINDEX_HASSUBTYPE) {
43609 UA_LOG_NODEID_INFO(&node->head.nodeId,
43610 UA_LOG_INFO_SESSION(&server->config.logger, session,
43611 "AddNode (%.*s): Variable not allowed "
43612 "to have HasSubType reference",
43613 (int)nodeIdStr.length, nodeIdStr.data));
43614 retval = UA_STATUSCODE_BADREFERENCENOTALLOWED;
43615 goto cleanup;
43616 }
43617 }
43618 }
43619
43620 /* Get the type node */
43621 if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
43622 node->head.nodeClass == UA_NODECLASS_VARIABLETYPE ||
43623 node->head.nodeClass == UA_NODECLASS_OBJECT) {
43624 type = getNodeType(server, head: &node->head);
43625 if(!type) {
43626 if(server->bootstrapNS0)
43627 goto constructor;
43628 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
43629 msg: "Node type not found");
43630 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43631 goto cleanup;
43632 }
43633 }
43634
43635 /* Initialize and typecheck the variable */
43636 if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
43637 node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) {
43638 /* Use attributes from the type. The value and value constraints are the
43639 * same for the variable and variabletype attribute structs. */
43640 retval = useVariableTypeAttributes(server, session,
43641 node: &node->variableNode,
43642 vt: &type->variableTypeNode);
43643 if(retval != UA_STATUSCODE_GOOD) {
43644 UA_LOG_NODEID_INFO(&node->head.nodeId,
43645 UA_LOG_INFO_SESSION(&server->config.logger, session,
43646 "AddNode (%.*s): Using attributes for from "
43647 "the variable type failed with error code %s",
43648 (int)nodeIdStr.length, nodeIdStr.data,
43649 UA_StatusCode_name(retval)));
43650 goto cleanup;
43651 }
43652
43653 /* Get a new pointer to the node. It might have been switched out */
43654#ifdef UA_ENABLE_IMMUTABLE_NODES
43655 UA_NODESTORE_RELEASE(server, node);
43656 node = UA_NODESTORE_GET(server, nodeId);
43657 if(!node || (node->head.nodeClass != UA_NODECLASS_VARIABLE &&
43658 node->head.nodeClass != UA_NODECLASS_VARIABLETYPE)) {
43659 retval = UA_STATUSCODE_BADINTERNALERROR;
43660 goto cleanup;
43661 }
43662#endif
43663
43664 /* Check if all attributes hold the constraints of the type now. The initial
43665 * attributes must type-check. The constructor might change the attributes
43666 * again. Then, the changes are type-checked by the normal write service. */
43667 retval = typeCheckVariableNode(server, session, node: &node->variableNode,
43668 vt: &type->variableTypeNode);
43669 if(retval != UA_STATUSCODE_GOOD) {
43670 UA_LOG_NODEID_INFO(&node->head.nodeId,
43671 UA_LOG_INFO_SESSION(&server->config.logger, session,
43672 "AddNode (%.*s): Type-checking "
43673 "failed with error code %s", (int)nodeIdStr.length,
43674 nodeIdStr.data, UA_StatusCode_name(retval)));
43675 goto cleanup;
43676 }
43677 }
43678
43679 /* Add (mandatory) child nodes from the type definition */
43680 if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
43681 node->head.nodeClass == UA_NODECLASS_OBJECT) {
43682 retval = addTypeChildren(server, session, nodeId, typeId: &type->head.nodeId);
43683 if(retval != UA_STATUSCODE_GOOD) {
43684 UA_LOG_NODEID_INFO(&node->head.nodeId,
43685 UA_LOG_INFO_SESSION(&server->config.logger, session,
43686 "AddNode (%.*s): Adding child nodes "
43687 "failed with error code %s", (int)nodeIdStr.length,
43688 nodeIdStr.data, UA_StatusCode_name(retval)));
43689 goto cleanup;
43690 }
43691 }
43692
43693 /* Add (mandatory) child nodes from the HasInterface references */
43694 if(node->head.nodeClass == UA_NODECLASS_OBJECT) {
43695 retval = addInterfaceChildren(server, session, nodeId, typeId: &type->head.nodeId);
43696 if(retval != UA_STATUSCODE_GOOD) {
43697 UA_LOG_NODEID_INFO(&node->head.nodeId,
43698 UA_LOG_INFO_SESSION(&server->config.logger, session,
43699 "AddNode (%.*s): Adding child nodes "
43700 "interface failed with error code %s",
43701 (int)nodeIdStr.length, nodeIdStr.data,
43702 UA_StatusCode_name(retval)));
43703 goto cleanup;
43704 }
43705 }
43706
43707 /* Set variables to dynamic (source and server timestamps are meaningful) if
43708 * they fulfill some conditions */
43709 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
43710 retval = checkSetIsDynamicVariable(server, session, nodeId);
43711 if(retval != UA_STATUSCODE_GOOD)
43712 goto cleanup;
43713 }
43714
43715 /* Call the constructor(s) */
43716 constructor:
43717 if(!node->head.constructed)
43718 retval = recursiveCallConstructors(server, session, nodeId, type);
43719 if(retval != UA_STATUSCODE_GOOD) {
43720 UA_LOG_NODEID_INFO(&node->head.nodeId,
43721 UA_LOG_INFO_SESSION(&server->config.logger, session,
43722 "AddNode (%.*s): Calling the node constructor(s) "
43723 "failed with status code %s", (int)nodeIdStr.length,
43724 nodeIdStr.data, UA_StatusCode_name(retval)));
43725 }
43726
43727 cleanup:
43728 if(type)
43729 UA_NODESTORE_RELEASE(server, type);
43730 if(node)
43731 UA_NODESTORE_RELEASE(server, node);
43732 if(retval != UA_STATUSCODE_GOOD)
43733 deleteNode(server, nodeId: *nodeId, true);
43734 return retval;
43735}
43736
43737static void
43738Operation_addNode(UA_Server *server, UA_Session *session, void *nodeContext,
43739 const UA_AddNodesItem *item, UA_AddNodesResult *result) {
43740 result->statusCode =
43741 Operation_addNode_begin(server, session, nodeContext,
43742 item, parentNodeId: &item->parentNodeId.nodeId,
43743 referenceTypeId: &item->referenceTypeId, outNewNodeId: &result->addedNodeId);
43744 if(result->statusCode != UA_STATUSCODE_GOOD)
43745 return;
43746
43747 /* AddNodes_finish */
43748 result->statusCode = AddNode_finish(server, session, nodeId: &result->addedNodeId);
43749
43750 /* If finishing failed, the node was deleted */
43751 if(result->statusCode != UA_STATUSCODE_GOOD)
43752 UA_NodeId_clear(p: &result->addedNodeId);
43753}
43754
43755void
43756Service_AddNodes(UA_Server *server, UA_Session *session,
43757 const UA_AddNodesRequest *request,
43758 UA_AddNodesResponse *response) {
43759 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing AddNodesRequest");
43760 UA_LOCK_ASSERT(&server->serviceMutex, 1);
43761
43762 if(server->config.maxNodesPerNodeManagement != 0 &&
43763 request->nodesToAddSize > server->config.maxNodesPerNodeManagement) {
43764 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
43765 return;
43766 }
43767
43768 response->responseHeader.serviceResult =
43769 UA_Server_processServiceOperations(server, session,
43770 operationCallback: (UA_ServiceOperation)Operation_addNode, NULL,
43771 requestOperations: &request->nodesToAddSize,
43772 requestOperationsType: &UA_TYPES[UA_TYPES_ADDNODESITEM],
43773 responseOperations: &response->resultsSize,
43774 responseOperationsType: &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
43775}
43776
43777UA_StatusCode
43778addNode(UA_Server *server, const UA_NodeClass nodeClass, const UA_NodeId *requestedNewNodeId,
43779 const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
43780 const UA_QualifiedName browseName, const UA_NodeId *typeDefinition,
43781 const UA_NodeAttributes *attr, const UA_DataType *attributeType,
43782 void *nodeContext, UA_NodeId *outNewNodeId) {
43783 UA_LOCK_ASSERT(&server->serviceMutex, 1);
43784
43785 /* Create the AddNodesItem */
43786 UA_AddNodesItem item;
43787 UA_AddNodesItem_init(p: &item);
43788 item.nodeClass = nodeClass;
43789 item.requestedNewNodeId.nodeId = *requestedNewNodeId;
43790 item.browseName = browseName;
43791 item.parentNodeId.nodeId = *parentNodeId;
43792 item.referenceTypeId = *referenceTypeId;
43793 item.typeDefinition.nodeId = *typeDefinition;
43794 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes,
43795 p: (void*)(uintptr_t)attr, type: attributeType);
43796
43797 /* Call the normal addnodes service */
43798 UA_AddNodesResult result;
43799 UA_AddNodesResult_init(p: &result);
43800 Operation_addNode(server, session: &server->adminSession, nodeContext, item: &item, result: &result);
43801 if(outNewNodeId)
43802 *outNewNodeId = result.addedNodeId;
43803 else
43804 UA_NodeId_clear(p: &result.addedNodeId);
43805 return result.statusCode;
43806}
43807
43808UA_StatusCode
43809__UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
43810 const UA_NodeId *requestedNewNodeId,
43811 const UA_NodeId *parentNodeId,
43812 const UA_NodeId *referenceTypeId,
43813 const UA_QualifiedName browseName,
43814 const UA_NodeId *typeDefinition,
43815 const UA_NodeAttributes *attr,
43816 const UA_DataType *attributeType,
43817 void *nodeContext, UA_NodeId *outNewNodeId) {
43818 UA_LOCK(&server->serviceMutex);
43819 UA_StatusCode reval =
43820 addNode(server, nodeClass, requestedNewNodeId, parentNodeId,
43821 referenceTypeId, browseName, typeDefinition, attr,
43822 attributeType, nodeContext, outNewNodeId);
43823 UA_UNLOCK(&server->serviceMutex);
43824 return reval;
43825}
43826
43827UA_StatusCode
43828UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass,
43829 const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
43830 const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
43831 const UA_NodeId typeDefinition, const void *attr,
43832 const UA_DataType *attributeType, void *nodeContext,
43833 UA_NodeId *outNewNodeId) {
43834 UA_AddNodesItem item;
43835 UA_AddNodesItem_init(p: &item);
43836 item.nodeClass = nodeClass;
43837 item.requestedNewNodeId.nodeId = requestedNewNodeId;
43838 item.browseName = browseName;
43839 item.typeDefinition.nodeId = typeDefinition;
43840 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes,
43841 p: (void*)(uintptr_t)attr, type: attributeType);
43842
43843 UA_LOCK(&server->serviceMutex);
43844 UA_StatusCode retval =
43845 Operation_addNode_begin(server, session: &server->adminSession, nodeContext, item: &item,
43846 parentNodeId: &parentNodeId, referenceTypeId: &referenceTypeId, outNewNodeId);
43847 UA_UNLOCK(&server->serviceMutex);
43848 return retval;
43849}
43850
43851UA_StatusCode
43852UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId) {
43853 UA_LOCK(&server->serviceMutex);
43854 UA_StatusCode retval = AddNode_finish(server, session: &server->adminSession, nodeId: &nodeId);
43855 UA_UNLOCK(&server->serviceMutex);
43856 return retval;
43857}
43858
43859/****************/
43860/* Delete Nodes */
43861/****************/
43862
43863static void
43864Operation_deleteReference(UA_Server *server, UA_Session *session, void *context,
43865 const UA_DeleteReferencesItem *item, UA_StatusCode *retval);
43866
43867/* Remove references to this node (in the other nodes) */
43868static void
43869removeIncomingReferences(UA_Server *server, UA_Session *session, const UA_NodeHead *head) {
43870 UA_DeleteReferencesItem item;
43871 UA_DeleteReferencesItem_init(p: &item);
43872 item.targetNodeId.nodeId = head->nodeId;
43873 item.deleteBidirectional = false;
43874
43875 UA_StatusCode dummy;
43876 for(size_t i = 0; i < head->referencesSize; ++i) {
43877 const UA_NodeReferenceKind *rk = &head->references[i];
43878 item.isForward = rk->isInverse;
43879 item.referenceTypeId =
43880 *UA_NODESTORE_GETREFERENCETYPEID(server, rk->referenceTypeIndex);
43881 const UA_ReferenceTarget *t = NULL;
43882 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
43883 if(!UA_NodePointer_isLocal(np: t->targetId))
43884 continue;
43885 item.sourceNodeId = UA_NodePointer_toNodeId(np: t->targetId);
43886 Operation_deleteReference(server, session, NULL, item: &item, retval: &dummy);
43887 }
43888 }
43889}
43890
43891/* A node is auto-deleted if all its hierarchical parents are being deleted */
43892static UA_Boolean
43893hasParentRef(const UA_NodeHead *head, const UA_ReferenceTypeSet *refSet,
43894 RefTree *refTree) {
43895 for(size_t i = 0; i < head->referencesSize; i++) {
43896 const UA_NodeReferenceKind *rk = &head->references[i];
43897 if(!rk->isInverse)
43898 continue;
43899 if(!UA_ReferenceTypeSet_contains(set: refSet, index: rk->referenceTypeIndex))
43900 continue;
43901 const UA_ReferenceTarget *t = NULL;
43902 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
43903 if(!UA_NodePointer_isLocal(np: t->targetId))
43904 continue;
43905 UA_NodeId tmpId = UA_NodePointer_toNodeId(np: t->targetId);
43906 if(!RefTree_containsNodeId(rt: refTree, target: &tmpId))
43907 return true;
43908 }
43909 }
43910 return false;
43911}
43912
43913static void
43914deconstructNodeSet(UA_Server *server, UA_Session *session,
43915 UA_ReferenceTypeSet *hierarchRefsSet, RefTree *refTree) {
43916 /* Deconstruct the nodes based on the RefTree entries, parent nodes first */
43917 for(size_t i = 0; i < refTree->size; i++) {
43918 const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[i].nodeId);
43919 if(!member)
43920 continue;
43921
43922 /* Call the type-level destructor */
43923 void *context = member->head.context; /* No longer needed after this function */
43924 if(member->head.nodeClass == UA_NODECLASS_OBJECT ||
43925 member->head.nodeClass == UA_NODECLASS_VARIABLE) {
43926 const UA_Node *type = getNodeType(server, head: &member->head);
43927 if(type) {
43928 /* Get the lifecycle */
43929 const UA_NodeTypeLifecycle *lifecycle;
43930 if(member->head.nodeClass == UA_NODECLASS_OBJECT)
43931 lifecycle = &type->objectTypeNode.lifecycle;
43932 else
43933 lifecycle = &type->variableTypeNode.lifecycle;
43934
43935 /* Call the destructor */
43936 if(lifecycle->destructor) {
43937 UA_UNLOCK(&server->serviceMutex);
43938 lifecycle->destructor(server,
43939 &session->sessionId, session->sessionHandle,
43940 &type->head.nodeId, type->head.context,
43941 &member->head.nodeId, &context);
43942 UA_LOCK(&server->serviceMutex);
43943 }
43944
43945 /* Release the type node */
43946 UA_NODESTORE_RELEASE(server, type);
43947 }
43948 }
43949
43950 /* Call the global destructor */
43951 if(server->config.nodeLifecycle.destructor) {
43952 UA_UNLOCK(&server->serviceMutex);
43953 server->config.nodeLifecycle.destructor(server, &session->sessionId,
43954 session->sessionHandle,
43955 &member->head.nodeId, context);
43956 UA_LOCK(&server->serviceMutex);
43957 }
43958
43959 /* Release the node. Don't access the node context from here on. */
43960 UA_NODESTORE_RELEASE(server, member);
43961
43962 /* Set the constructed flag to false */
43963 UA_Server_editNode(server, session: &server->adminSession, nodeId: &refTree->targets[i].nodeId,
43964 callback: (UA_EditNodeCallback)setDeconstructedNode, NULL);
43965 }
43966}
43967
43968/* The processNodeLayer function searches all children's of the head node and
43969 * adds the children node to the RefTree if all incoming references sources are
43970 * contained in the RefTree (No external references to this node --> node can be
43971 * deleted) */
43972static UA_StatusCode
43973autoDeleteChildren(UA_Server *server, UA_Session *session, RefTree *refTree,
43974 const UA_ReferenceTypeSet *hierarchRefsSet, const UA_NodeHead *head){
43975 UA_StatusCode res = UA_STATUSCODE_GOOD;
43976 for(size_t i = 0; i < head->referencesSize; ++i) {
43977 /* Check if the ReferenceType is hierarchical */
43978 UA_NodeReferenceKind *refs = &head->references[i];
43979 if(!UA_ReferenceTypeSet_contains(set: hierarchRefsSet, index: refs->referenceTypeIndex))
43980 continue;
43981
43982 /* Check if the references are forward (to a child) */
43983 if(refs->isInverse)
43984 continue;
43985
43986 /* Loop over the references */
43987 const UA_ReferenceTarget *t = NULL;
43988 while((t = UA_NodeReferenceKind_iterate(rk: refs, prev: t))) {
43989 /* Get the child */
43990 const UA_Node *child = UA_NODESTORE_GETFROMREF(server, target: t->targetId);
43991 if(!child)
43992 continue;
43993
43994 /* Only delete child nodes that have no other parent */
43995 if(!hasParentRef(head: &child->head, refSet: hierarchRefsSet, refTree))
43996 res = RefTree_addNodeId(rt: refTree, target: &child->head.nodeId, NULL);
43997 UA_NODESTORE_RELEASE(server, child);
43998 if(res != UA_STATUSCODE_GOOD)
43999 return res;
44000 }
44001 }
44002 return UA_STATUSCODE_GOOD;
44003}
44004
44005/* Build up an ordered set (tree) of all nodes that can be deleted. Step through
44006 * the ordered set in order to avoid recursion. */
44007static UA_StatusCode
44008buildDeleteNodeSet(UA_Server *server, UA_Session *session,
44009 const UA_ReferenceTypeSet *hierarchRefsSet,
44010 const UA_NodeId *initial, UA_Boolean removeTargetRefs,
44011 RefTree *refTree) {
44012 /* Add the initial node to delete */
44013 UA_StatusCode res = RefTree_addNodeId(rt: refTree, target: initial, NULL);
44014 if(res != UA_STATUSCODE_GOOD)
44015 return res;
44016
44017 /* Find out which hierarchical children should also be deleted. We know
44018 * there are no "external" ExpandedNodeId in the RefTree. */
44019 size_t pos = 0;
44020 while(pos < refTree->size) {
44021 const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[pos].nodeId);
44022 pos++;
44023 if(!member)
44024 continue;
44025 res |= autoDeleteChildren(server, session, refTree, hierarchRefsSet, head: &member->head);
44026 UA_NODESTORE_RELEASE(server, member);
44027 }
44028 return res;
44029}
44030
44031static void
44032deleteNodeSet(UA_Server *server, UA_Session *session,
44033 const UA_ReferenceTypeSet *hierarchRefsSet,
44034 UA_Boolean removeTargetRefs, RefTree *refTree) {
44035 /* Delete the nodes based on the RefTree entries */
44036 for(size_t i = refTree->size; i > 0; --i) {
44037 const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[i-1].nodeId);
44038 if(!member)
44039 continue;
44040 UA_NODESTORE_RELEASE(server, member);
44041 if(removeTargetRefs)
44042 removeIncomingReferences(server, session, head: &member->head);
44043 UA_NODESTORE_REMOVE(server, &member->head.nodeId);
44044 }
44045}
44046
44047static void
44048deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
44049 const UA_DeleteNodesItem *item, UA_StatusCode *result) {
44050 /* Do not check access for server */
44051 if(session != &server->adminSession && server->config.accessControl.allowDeleteNode) {
44052 UA_UNLOCK(&server->serviceMutex);
44053 if(!server->config.accessControl.
44054 allowDeleteNode(server, &server->config.accessControl,
44055 &session->sessionId, session->sessionHandle, item)) {
44056 UA_LOCK(&server->serviceMutex);
44057 *result = UA_STATUSCODE_BADUSERACCESSDENIED;
44058 return;
44059 }
44060 UA_LOCK(&server->serviceMutex);
44061 }
44062
44063 const UA_Node *node = UA_NODESTORE_GET(server, &item->nodeId);
44064 if(!node) {
44065 *result = UA_STATUSCODE_BADNODEIDUNKNOWN;
44066 return;
44067 }
44068
44069 if(UA_Node_hasSubTypeOrInstances(head: &node->head)) {
44070 UA_LOG_NODEID_INFO(&node->head.nodeId,
44071 UA_LOG_INFO_SESSION(&server->config.logger, session, "DeleteNode (%.*s): "
44072 "Cannot delete a type node with active instances or "
44073 "subtypes", (int)nodeIdStr.length, nodeIdStr.data));
44074 UA_NODESTORE_RELEASE(server, node);
44075 *result = UA_STATUSCODE_BADINTERNALERROR;
44076 return;
44077 }
44078
44079 /* TODO: Check if the information model consistency is violated */
44080 /* TODO: Check if the node is a mandatory child of a parent */
44081
44082 /* Relase the node. Don't access the pointer after this! */
44083 UA_NODESTORE_RELEASE(server, node);
44084
44085 /* A node can be referenced with hierarchical references from several
44086 * parents in the information model. (But not in a circular way.) The
44087 * hierarchical references are checked to see if a node can be deleted.
44088 * Getting the type hierarchy can fail in case of low RAM. In that case the
44089 * nodes are always deleted. */
44090 UA_ReferenceTypeSet hierarchRefsSet;
44091 UA_NodeId hr = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
44092 *result = referenceTypeIndices(server, refType: &hr, indices: &hierarchRefsSet, true);
44093 if(*result != UA_STATUSCODE_GOOD)
44094 return;
44095
44096 /* The list of childs is needed for the deconstructing and deleting phase.
44097 * Within the processNodeLayer we generate a RefTree based set of childs
44098 * which can be deleted beside the parent node. */
44099 RefTree refTree;
44100 *result = RefTree_init(rt: &refTree);
44101 if(*result != UA_STATUSCODE_GOOD)
44102 return;
44103 *result = buildDeleteNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet, initial: &item->nodeId,
44104 removeTargetRefs: item->deleteTargetReferences, refTree: &refTree);
44105 if(*result != UA_STATUSCODE_GOOD) {
44106 UA_LOG_WARNING_SESSION(&server->config.logger, session,
44107 "DeleteNode: Incomplete lookup of nodes. "
44108 "Still deleting what we have.");
44109 /* Continue, so the RefTree is cleaned up. Return the error message
44110 * anyway. */
44111 }
44112
44113 /* Deconstruct, then delete, then clean up the set */
44114 deconstructNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet, refTree: &refTree);
44115 deleteNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet,
44116 removeTargetRefs: item->deleteTargetReferences, refTree: &refTree);
44117 RefTree_clear(rt: &refTree);
44118}
44119
44120void
44121Service_DeleteNodes(UA_Server *server, UA_Session *session,
44122 const UA_DeleteNodesRequest *request,
44123 UA_DeleteNodesResponse *response) {
44124 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
44125 "Processing DeleteNodesRequest");
44126 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44127
44128 if(server->config.maxNodesPerNodeManagement != 0 &&
44129 request->nodesToDeleteSize > server->config.maxNodesPerNodeManagement) {
44130 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
44131 return;
44132 }
44133
44134 response->responseHeader.serviceResult =
44135 UA_Server_processServiceOperations(server, session,
44136 operationCallback: (UA_ServiceOperation)deleteNodeOperation,
44137 NULL, requestOperations: &request->nodesToDeleteSize,
44138 requestOperationsType: &UA_TYPES[UA_TYPES_DELETENODESITEM],
44139 responseOperations: &response->resultsSize,
44140 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
44141}
44142
44143UA_StatusCode
44144UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
44145 UA_Boolean deleteReferences) {
44146 UA_LOCK(&server->serviceMutex);
44147 UA_StatusCode retval = deleteNode(server, nodeId, deleteReferences);
44148 UA_UNLOCK(&server->serviceMutex);
44149 return retval;
44150}
44151
44152UA_StatusCode
44153deleteNode(UA_Server *server, const UA_NodeId nodeId,
44154 UA_Boolean deleteReferences) {
44155 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44156 UA_DeleteNodesItem item;
44157 item.deleteTargetReferences = deleteReferences;
44158 item.nodeId = nodeId;
44159 UA_StatusCode retval = UA_STATUSCODE_GOOD;
44160 deleteNodeOperation(server, session: &server->adminSession, NULL, item: &item, result: &retval);
44161 return retval;
44162}
44163
44164/******************/
44165/* Add References */
44166/******************/
44167
44168struct AddNodeInfo {
44169 UA_Byte refTypeIndex;
44170 UA_Boolean isForward;
44171 const UA_ExpandedNodeId *targetNodeId;
44172 UA_UInt32 targetBrowseNameHash;
44173};
44174
44175static UA_StatusCode
44176addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node,
44177 const struct AddNodeInfo *info) {
44178 return UA_Node_addReference(node, refTypeIndex: info->refTypeIndex, isForward: info->isForward,
44179 targetNodeId: info->targetNodeId, targetBrowseNameHash: info->targetBrowseNameHash);
44180}
44181
44182static UA_StatusCode
44183deleteOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node,
44184 const UA_DeleteReferencesItem *item) {
44185 const UA_Node *refType = UA_NODESTORE_GET(server, &item->referenceTypeId);
44186 if(!refType)
44187 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
44188 if(refType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
44189 UA_NODESTORE_RELEASE(server, refType);
44190 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
44191 }
44192 UA_Byte refTypeIndex = refType->referenceTypeNode.referenceTypeIndex;
44193 UA_NODESTORE_RELEASE(server, refType);
44194 return UA_Node_deleteReference(node, refTypeIndex, isForward: item->isForward, targetNodeId: &item->targetNodeId);
44195}
44196
44197static void
44198Operation_addReference(UA_Server *server, UA_Session *session, void *context,
44199 const UA_AddReferencesItem *item, UA_StatusCode *retval) {
44200 (void)context;
44201 UA_assert(session);
44202
44203 /* Check access rights */
44204 if(session != &server->adminSession && server->config.accessControl.allowAddReference) {
44205 UA_UNLOCK(&server->serviceMutex);
44206 if (!server->config.accessControl.
44207 allowAddReference(server, &server->config.accessControl,
44208 &session->sessionId, session->sessionHandle, item)) {
44209 UA_LOCK(&server->serviceMutex);
44210 *retval = UA_STATUSCODE_BADUSERACCESSDENIED;
44211 return;
44212 }
44213 UA_LOCK(&server->serviceMutex);
44214 }
44215
44216 /* TODO: Currently no expandednodeids are allowed */
44217 if(item->targetServerUri.length > 0) {
44218 *retval = UA_STATUSCODE_BADNOTIMPLEMENTED;
44219 return;
44220 }
44221
44222 /* Check the ReferenceType and get the index */
44223 const UA_Node *refType = UA_NODESTORE_GET(server, &item->referenceTypeId);
44224 if(!refType) {
44225 *retval = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
44226 return;
44227 }
44228 if(refType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
44229 UA_NODESTORE_RELEASE(server, refType);
44230 *retval = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
44231 return;
44232 }
44233 UA_Byte refTypeIndex = refType->referenceTypeNode.referenceTypeIndex;
44234 UA_NODESTORE_RELEASE(server, refType);
44235
44236 /* Get the source and target node BrowseName hash */
44237 const UA_Node *targetNode = UA_NODESTORE_GET(server, &item->targetNodeId.nodeId);
44238 if(!targetNode) {
44239 *retval = UA_STATUSCODE_BADTARGETNODEIDINVALID;
44240 return;
44241 }
44242 UA_UInt32 targetNameHash = UA_QualifiedName_hash(q: &targetNode->head.browseName);
44243 UA_NODESTORE_RELEASE(server, targetNode);
44244
44245 const UA_Node *sourceNode = UA_NODESTORE_GET(server, &item->sourceNodeId);
44246 if(!sourceNode) {
44247 *retval = UA_STATUSCODE_BADSOURCENODEIDINVALID;
44248 return;
44249 }
44250 UA_UInt32 sourceNameHash = UA_QualifiedName_hash(q: &sourceNode->head.browseName);
44251 UA_NODESTORE_RELEASE(server, sourceNode);
44252
44253 /* Compute the BrowseName hash and release the target */
44254 struct AddNodeInfo info;
44255 info.refTypeIndex = refTypeIndex;
44256 info.targetNodeId = &item->targetNodeId;
44257 info.isForward = item->isForward;
44258 info.targetBrowseNameHash = targetNameHash;
44259
44260 /* Add the first direction */
44261 *retval = UA_Server_editNode(server, session, nodeId: &item->sourceNodeId,
44262 callback: (UA_EditNodeCallback)addOneWayReference, data: &info);
44263 UA_Boolean firstExisted = false;
44264 if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
44265 *retval = UA_STATUSCODE_GOOD;
44266 firstExisted = true;
44267 }
44268 if(*retval != UA_STATUSCODE_GOOD)
44269 return;
44270
44271 /* Add the second direction */
44272 UA_ExpandedNodeId target2;
44273 UA_ExpandedNodeId_init(p: &target2);
44274 target2.nodeId = item->sourceNodeId;
44275 info.targetNodeId = &target2;
44276 info.isForward = !info.isForward;
44277 info.targetBrowseNameHash = sourceNameHash;
44278 *retval = UA_Server_editNode(server, session, nodeId: &item->targetNodeId.nodeId,
44279 callback: (UA_EditNodeCallback)addOneWayReference, data: &info);
44280
44281 /* Second direction existed already */
44282 if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
44283 /* Calculate common duplicate reference not allowed result and set bad
44284 * result if BOTH directions already existed */
44285 if(UA_NodeId_equal(n1: &item->sourceNodeId, n2: &item->targetNodeId.nodeId)) {
44286 *retval = UA_STATUSCODE_GOOD;
44287 UA_LOG_INFO_SESSION(&server->config.logger, session, "The source node and the target node are identical. The check for duplicate references is skipped.");
44288 }
44289 else if(firstExisted) {
44290 *retval = UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
44291 return;
44292 }
44293 *retval = UA_STATUSCODE_GOOD;
44294 }
44295
44296 /* Remove first direction if the second direction failed */
44297 if(*retval != UA_STATUSCODE_GOOD && !firstExisted) {
44298 UA_DeleteReferencesItem deleteItem;
44299 deleteItem.sourceNodeId = item->sourceNodeId;
44300 deleteItem.referenceTypeId = item->referenceTypeId;
44301 deleteItem.isForward = item->isForward;
44302 deleteItem.targetNodeId = item->targetNodeId;
44303 deleteItem.deleteBidirectional = false;
44304 /* Ignore status code */
44305 UA_Server_editNode(server, session, nodeId: &item->sourceNodeId,
44306 callback: (UA_EditNodeCallback)deleteOneWayReference, data: &deleteItem);
44307 }
44308}
44309
44310void
44311Service_AddReferences(UA_Server *server, UA_Session *session,
44312 const UA_AddReferencesRequest *request,
44313 UA_AddReferencesResponse *response) {
44314 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
44315 "Processing AddReferencesRequest");
44316 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44317 UA_assert(session);
44318
44319 if(server->config.maxNodesPerNodeManagement != 0 &&
44320 request->referencesToAddSize > server->config.maxNodesPerNodeManagement) {
44321 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
44322 return;
44323 }
44324
44325 response->responseHeader.serviceResult =
44326 UA_Server_processServiceOperations(server, session,
44327 operationCallback: (UA_ServiceOperation)Operation_addReference,
44328 NULL, requestOperations: &request->referencesToAddSize,
44329 requestOperationsType: &UA_TYPES[UA_TYPES_ADDREFERENCESITEM],
44330 responseOperations: &response->resultsSize,
44331 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
44332}
44333
44334UA_StatusCode
44335UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
44336 const UA_NodeId refTypeId,
44337 const UA_ExpandedNodeId targetId,
44338 UA_Boolean isForward) {
44339 UA_AddReferencesItem item;
44340 UA_AddReferencesItem_init(p: &item);
44341 item.sourceNodeId = sourceId;
44342 item.referenceTypeId = refTypeId;
44343 item.isForward = isForward;
44344 item.targetNodeId = targetId;
44345
44346 UA_StatusCode retval = UA_STATUSCODE_GOOD;
44347 UA_LOCK(&server->serviceMutex);
44348 Operation_addReference(server, session: &server->adminSession, NULL, item: &item, retval: &retval);
44349 UA_UNLOCK(&server->serviceMutex);
44350 return retval;
44351}
44352
44353/*********************/
44354/* Delete References */
44355/*********************/
44356
44357static void
44358Operation_deleteReference(UA_Server *server, UA_Session *session, void *context,
44359 const UA_DeleteReferencesItem *item, UA_StatusCode *retval) {
44360 /* Do not check access for server */
44361 if(session != &server->adminSession &&
44362 server->config.accessControl.allowDeleteReference) {
44363 UA_UNLOCK(&server->serviceMutex);
44364 if (!server->config.accessControl.
44365 allowDeleteReference(server, &server->config.accessControl,
44366 &session->sessionId, session->sessionHandle, item)){
44367 UA_LOCK(&server->serviceMutex);
44368 *retval = UA_STATUSCODE_BADUSERACCESSDENIED;
44369 return;
44370 }
44371 UA_LOCK(&server->serviceMutex);
44372 }
44373
44374 // TODO: Check consistency constraints, remove the references.
44375 *retval = UA_Server_editNode(server, session, nodeId: &item->sourceNodeId,
44376 callback: (UA_EditNodeCallback)deleteOneWayReference,
44377 /* cast away const qualifier because callback
44378 * uses it anyway */
44379 data: (UA_DeleteReferencesItem *)(uintptr_t)item);
44380 if(*retval != UA_STATUSCODE_GOOD)
44381 return;
44382
44383 if(!item->deleteBidirectional || item->targetNodeId.serverIndex != 0)
44384 return;
44385
44386 UA_DeleteReferencesItem secondItem;
44387 UA_DeleteReferencesItem_init(p: &secondItem);
44388 secondItem.isForward = !item->isForward;
44389 secondItem.sourceNodeId = item->targetNodeId.nodeId;
44390 secondItem.targetNodeId.nodeId = item->sourceNodeId;
44391 secondItem.referenceTypeId = item->referenceTypeId;
44392 *retval = UA_Server_editNode(server, session, nodeId: &secondItem.sourceNodeId,
44393 callback: (UA_EditNodeCallback)deleteOneWayReference,
44394 data: &secondItem);
44395}
44396
44397void
44398Service_DeleteReferences(UA_Server *server, UA_Session *session,
44399 const UA_DeleteReferencesRequest *request,
44400 UA_DeleteReferencesResponse *response) {
44401 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
44402 "Processing DeleteReferencesRequest");
44403 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44404
44405 if(server->config.maxNodesPerNodeManagement != 0 &&
44406 request->referencesToDeleteSize > server->config.maxNodesPerNodeManagement) {
44407 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
44408 return;
44409 }
44410
44411 response->responseHeader.serviceResult =
44412 UA_Server_processServiceOperations(server, session,
44413 operationCallback: (UA_ServiceOperation)Operation_deleteReference,
44414 NULL, requestOperations: &request->referencesToDeleteSize,
44415 requestOperationsType: &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM],
44416 responseOperations: &response->resultsSize,
44417 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
44418}
44419
44420UA_StatusCode
44421UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
44422 const UA_NodeId referenceTypeId, UA_Boolean isForward,
44423 const UA_ExpandedNodeId targetNodeId,
44424 UA_Boolean deleteBidirectional) {
44425 UA_DeleteReferencesItem item;
44426 item.sourceNodeId = sourceNodeId;
44427 item.referenceTypeId = referenceTypeId;
44428 item.isForward = isForward;
44429 item.targetNodeId = targetNodeId;
44430 item.deleteBidirectional = deleteBidirectional;
44431
44432 UA_StatusCode retval = UA_STATUSCODE_GOOD;
44433 UA_LOCK(&server->serviceMutex);
44434 Operation_deleteReference(server, session: &server->adminSession, NULL, item: &item, retval: &retval);
44435 UA_UNLOCK(&server->serviceMutex);
44436 return retval;
44437}
44438
44439/**********************/
44440/* Set Value Callback */
44441/**********************/
44442
44443static UA_StatusCode
44444setValueCallback(UA_Server *server, UA_Session *session,
44445 UA_VariableNode *node, const UA_ValueCallback *callback) {
44446 if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
44447 return UA_STATUSCODE_BADNODECLASSINVALID;
44448 node->value.data.callback = *callback;
44449 return UA_STATUSCODE_GOOD;
44450}
44451
44452UA_StatusCode
44453UA_Server_setVariableNode_valueCallback(UA_Server *server,
44454 const UA_NodeId nodeId,
44455 const UA_ValueCallback callback) {
44456 UA_LOCK(&server->serviceMutex);
44457 UA_StatusCode retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44458 callback: (UA_EditNodeCallback)setValueCallback,
44459 /* cast away const because
44460 * callback uses const anyway */
44461 data: (UA_ValueCallback *)(uintptr_t) &callback);
44462 UA_UNLOCK(&server->serviceMutex);
44463 return retval;
44464}
44465
44466/***************************************************/
44467/* Special Handling of Variables with Data Sources */
44468/***************************************************/
44469
44470UA_StatusCode
44471UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
44472 const UA_NodeId parentNodeId,
44473 const UA_NodeId referenceTypeId,
44474 const UA_QualifiedName browseName,
44475 const UA_NodeId typeDefinition,
44476 const UA_VariableAttributes attr,
44477 const UA_DataSource dataSource,
44478 void *nodeContext, UA_NodeId *outNewNodeId) {
44479 UA_AddNodesItem item;
44480 UA_AddNodesItem_init(p: &item);
44481 item.nodeClass = UA_NODECLASS_VARIABLE;
44482 item.requestedNewNodeId.nodeId = requestedNewNodeId;
44483 item.browseName = browseName;
44484 UA_ExpandedNodeId typeDefinitionId;
44485 UA_ExpandedNodeId_init(p: &typeDefinitionId);
44486 typeDefinitionId.nodeId = typeDefinition;
44487 item.typeDefinition = typeDefinitionId;
44488 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, p: (void*)(uintptr_t)&attr,
44489 type: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]);
44490 UA_NodeId newNodeId;
44491 if(!outNewNodeId) {
44492 newNodeId = UA_NODEID_NULL;
44493 outNewNodeId = &newNodeId;
44494 }
44495
44496 UA_LOCK(&server->serviceMutex);
44497 /* Create the node and add it to the nodestore */
44498 UA_StatusCode retval = AddNode_raw(server, session: &server->adminSession, nodeContext,
44499 item: &item, outNewNodeId);
44500 if(retval != UA_STATUSCODE_GOOD)
44501 goto cleanup;
44502
44503 /* Set the data source */
44504 retval = setVariableNode_dataSource(server, nodeId: *outNewNodeId, dataSource);
44505 if(retval != UA_STATUSCODE_GOOD)
44506 goto cleanup;
44507
44508 /* Typecheck and add references to parent and type definition */
44509 retval = AddNode_addRefs(server, session: &server->adminSession, nodeId: outNewNodeId, parentNodeId: &parentNodeId,
44510 referenceTypeId: &referenceTypeId, typeDefinitionId: &typeDefinition);
44511 if(retval != UA_STATUSCODE_GOOD)
44512 goto cleanup;
44513
44514 /* Call the constructors */
44515 retval = AddNode_finish(server, session: &server->adminSession, nodeId: outNewNodeId);
44516
44517 cleanup:
44518 UA_UNLOCK(&server->serviceMutex);
44519 if(outNewNodeId == &newNodeId)
44520 UA_NodeId_clear(p: &newNodeId);
44521
44522 return retval;
44523}
44524
44525static UA_StatusCode
44526setDataSource(UA_Server *server, UA_Session *session,
44527 UA_VariableNode *node, const UA_DataSource *dataSource) {
44528 if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
44529 return UA_STATUSCODE_BADNODECLASSINVALID;
44530 if(node->valueSource == UA_VALUESOURCE_DATA)
44531 UA_DataValue_clear(p: &node->value.data.value);
44532 node->value.dataSource = *dataSource;
44533 node->valueSource = UA_VALUESOURCE_DATASOURCE;
44534 return UA_STATUSCODE_GOOD;
44535}
44536
44537UA_StatusCode
44538setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
44539 const UA_DataSource dataSource) {
44540 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44541 return UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44542 callback: (UA_EditNodeCallback)setDataSource,
44543 /* casting away const because callback casts it back anyway */
44544 data: (UA_DataSource *) (uintptr_t)&dataSource);
44545}
44546
44547UA_StatusCode
44548UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
44549 const UA_DataSource dataSource) {
44550 UA_LOCK(&server->serviceMutex);
44551 UA_StatusCode retval = setVariableNode_dataSource(server, nodeId, dataSource);
44552 UA_UNLOCK(&server->serviceMutex);
44553 return retval;
44554}
44555
44556/******************************/
44557/* Set External Value Source */
44558/******************************/
44559static UA_StatusCode
44560setExternalValueSource(UA_Server *server, UA_Session *session,
44561 UA_VariableNode *node, const UA_ValueBackend *externalValueSource) {
44562 if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
44563 return UA_STATUSCODE_BADNODECLASSINVALID;
44564 node->valueBackend.backendType = UA_VALUEBACKENDTYPE_EXTERNAL;
44565 node->valueBackend.backend.external.value =
44566 externalValueSource->backend.external.value;
44567 node->valueBackend.backend.external.callback.notificationRead =
44568 externalValueSource->backend.external.callback.notificationRead;
44569 node->valueBackend.backend.external.callback.userWrite =
44570 externalValueSource->backend.external.callback.userWrite;
44571 return UA_STATUSCODE_GOOD;
44572}
44573
44574/****************************/
44575/* Set Data Source Callback */
44576/****************************/
44577static UA_StatusCode
44578setDataSourceCallback(UA_Server *server, UA_Session *session,
44579 UA_VariableNode *node, const UA_DataSource *dataSource) {
44580 if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
44581 return UA_STATUSCODE_BADNODECLASSINVALID;
44582 node->valueBackend.backendType = UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK;
44583 node->valueBackend.backend.dataSource.read = dataSource->read;
44584 node->valueBackend.backend.dataSource.write = dataSource->write;
44585 return UA_STATUSCODE_GOOD;
44586}
44587
44588/**********************/
44589/* Set Value Backend */
44590/**********************/
44591
44592UA_StatusCode
44593UA_Server_setVariableNode_valueBackend(UA_Server *server, const UA_NodeId nodeId,
44594 const UA_ValueBackend valueBackend){
44595 UA_StatusCode retval = UA_STATUSCODE_GOOD;
44596 UA_LOCK(&server->serviceMutex);
44597 switch(valueBackend.backendType){
44598 case UA_VALUEBACKENDTYPE_NONE:
44599 UA_UNLOCK(&server->serviceMutex);
44600 return UA_STATUSCODE_BADCONFIGURATIONERROR;
44601 case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
44602 retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44603 callback: (UA_EditNodeCallback) setDataSourceCallback,
44604 data: (UA_DataSource *)(uintptr_t) &valueBackend.backend.dataSource);
44605 break;
44606 case UA_VALUEBACKENDTYPE_INTERNAL:
44607 break;
44608 case UA_VALUEBACKENDTYPE_EXTERNAL:
44609 retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44610 callback: (UA_EditNodeCallback) setExternalValueSource,
44611 /* cast away const because callback uses const anyway */
44612 data: (UA_ValueCallback *)(uintptr_t) &valueBackend);
44613 break;
44614 }
44615
44616
44617 // UA_StatusCode retval = UA_Server_editNode(server, &server->adminSession, &nodeId,
44618 // (UA_EditNodeCallback)setValueCallback,
44619 /* cast away const because callback uses const anyway */
44620 // (UA_ValueCallback *)(uintptr_t) &callback);
44621
44622
44623 UA_UNLOCK(&server->serviceMutex);
44624 return retval;
44625}
44626
44627
44628/************************************/
44629/* Special Handling of Method Nodes */
44630/************************************/
44631
44632#ifdef UA_ENABLE_METHODCALLS
44633
44634static const UA_NodeId hasproperty = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASPROPERTY}};
44635static const UA_NodeId propertytype = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_PROPERTYTYPE}};
44636
44637static UA_StatusCode
44638UA_Server_addMethodNodeEx_finish(UA_Server *server, const UA_NodeId nodeId,
44639 UA_MethodCallback method,
44640 const size_t inputArgumentsSize,
44641 const UA_Argument *inputArguments,
44642 const UA_NodeId inputArgumentsRequestedNewNodeId,
44643 UA_NodeId *inputArgumentsOutNewNodeId,
44644 const size_t outputArgumentsSize,
44645 const UA_Argument *outputArguments,
44646 const UA_NodeId outputArgumentsRequestedNewNodeId,
44647 UA_NodeId *outputArgumentsOutNewNodeId) {
44648 /* Browse to see which argument nodes exist */
44649 UA_BrowseDescription bd;
44650 UA_BrowseDescription_init(p: &bd);
44651 bd.nodeId = nodeId;
44652 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
44653 bd.includeSubtypes = false;
44654 bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
44655 bd.nodeClassMask = UA_NODECLASS_VARIABLE;
44656 bd.resultMask = UA_BROWSERESULTMASK_BROWSENAME;
44657
44658 UA_BrowseResult br;
44659 UA_BrowseResult_init(p: &br);
44660 UA_UInt32 maxrefs = 0;
44661 Operation_Browse(server, session: &server->adminSession, maxrefs: &maxrefs, descr: &bd, result: &br);
44662
44663 UA_StatusCode retval = br.statusCode;
44664 if(retval != UA_STATUSCODE_GOOD) {
44665 deleteNode(server, nodeId, true);
44666 UA_BrowseResult_clear(p: &br);
44667 return retval;
44668 }
44669
44670 /* Filter out the argument nodes */
44671 UA_NodeId inputArgsId = UA_NODEID_NULL;
44672 UA_NodeId outputArgsId = UA_NODEID_NULL;
44673 const UA_QualifiedName inputArgsName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "InputArguments");
44674 const UA_QualifiedName outputArgsName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "OutputArguments");
44675 for(size_t i = 0; i < br.referencesSize; i++) {
44676 UA_ReferenceDescription *rd = &br.references[i];
44677 if(rd->browseName.namespaceIndex == 0 &&
44678 UA_String_equal(s1: &rd->browseName.name, s2: &inputArgsName.name))
44679 inputArgsId = rd->nodeId.nodeId;
44680 else if(rd->browseName.namespaceIndex == 0 &&
44681 UA_String_equal(s1: &rd->browseName.name, s2: &outputArgsName.name))
44682 outputArgsId = rd->nodeId.nodeId;
44683 }
44684
44685 /* Add the Input Arguments VariableNode */
44686 if(inputArgumentsSize > 0 && UA_NodeId_isNull(p: &inputArgsId)) {
44687 UA_VariableAttributes attr = UA_VariableAttributes_default;
44688 char *name = "InputArguments";
44689 attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name);
44690 attr.dataType = UA_TYPES[UA_TYPES_ARGUMENT].typeId;
44691 attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
44692 UA_UInt32 inputArgsSize32 = (UA_UInt32)inputArgumentsSize;
44693 attr.arrayDimensions = &inputArgsSize32;
44694 attr.arrayDimensionsSize = 1;
44695 UA_Variant_setArray(v: &attr.value, array: (void *)(uintptr_t)inputArguments,
44696 arraySize: inputArgumentsSize, type: &UA_TYPES[UA_TYPES_ARGUMENT]);
44697 retval = addNode(server, nodeClass: UA_NODECLASS_VARIABLE, requestedNewNodeId: &inputArgumentsRequestedNewNodeId,
44698 parentNodeId: &nodeId, referenceTypeId: &hasproperty, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name),
44699 typeDefinition: &propertytype, attr: (const UA_NodeAttributes*)&attr,
44700 attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
44701 NULL, outNewNodeId: &inputArgsId);
44702 if(retval != UA_STATUSCODE_GOOD)
44703 goto error;
44704 }
44705
44706 /* Add the Output Arguments VariableNode */
44707 if(outputArgumentsSize > 0 && UA_NodeId_isNull(p: &outputArgsId)) {
44708 UA_VariableAttributes attr = UA_VariableAttributes_default;
44709 char *name = "OutputArguments";
44710 attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name);
44711 attr.dataType = UA_TYPES[UA_TYPES_ARGUMENT].typeId;
44712 attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
44713 UA_UInt32 outputArgsSize32 = (UA_UInt32)outputArgumentsSize;
44714 attr.arrayDimensions = &outputArgsSize32;
44715 attr.arrayDimensionsSize = 1;
44716 UA_Variant_setArray(v: &attr.value, array: (void *)(uintptr_t)outputArguments,
44717 arraySize: outputArgumentsSize, type: &UA_TYPES[UA_TYPES_ARGUMENT]);
44718 retval = addNode(server, nodeClass: UA_NODECLASS_VARIABLE, requestedNewNodeId: &outputArgumentsRequestedNewNodeId,
44719 parentNodeId: &nodeId, referenceTypeId: &hasproperty, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name),
44720 typeDefinition: &propertytype, attr: (const UA_NodeAttributes*)&attr,
44721 attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
44722 NULL, outNewNodeId: &outputArgsId);
44723 if(retval != UA_STATUSCODE_GOOD)
44724 goto error;
44725 }
44726
44727 retval = setMethodNode_callback(server, methodNodeId: nodeId, methodCallback: method);
44728 if(retval != UA_STATUSCODE_GOOD)
44729 goto error;
44730
44731 /* Call finish to add the parent reference */
44732 retval = AddNode_finish(server, session: &server->adminSession, nodeId: &nodeId);
44733 if(retval != UA_STATUSCODE_GOOD)
44734 goto error;
44735
44736 if(inputArgumentsOutNewNodeId != NULL) {
44737 UA_NodeId_copy(src: &inputArgsId, dst: inputArgumentsOutNewNodeId);
44738 }
44739 if(outputArgumentsOutNewNodeId != NULL) {
44740 UA_NodeId_copy(src: &outputArgsId, dst: outputArgumentsOutNewNodeId);
44741 }
44742 UA_BrowseResult_clear(p: &br);
44743 return retval;
44744
44745error:
44746 deleteNode(server, nodeId, true);
44747 deleteNode(server, nodeId: inputArgsId, true);
44748 deleteNode(server, nodeId: outputArgsId, true);
44749 UA_BrowseResult_clear(p: &br);
44750 return retval;
44751}
44752
44753UA_StatusCode
44754UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
44755 UA_MethodCallback method,
44756 size_t inputArgumentsSize,
44757 const UA_Argument* inputArguments,
44758 size_t outputArgumentsSize,
44759 const UA_Argument* outputArguments) {
44760 UA_LOCK(&server->serviceMutex);
44761 UA_StatusCode retval =
44762 UA_Server_addMethodNodeEx_finish(server, nodeId, method,
44763 inputArgumentsSize, inputArguments,
44764 inputArgumentsRequestedNewNodeId: UA_NODEID_NULL, NULL,
44765 outputArgumentsSize, outputArguments,
44766 outputArgumentsRequestedNewNodeId: UA_NODEID_NULL, NULL);
44767 UA_UNLOCK(&server->serviceMutex);
44768 return retval;
44769}
44770
44771UA_StatusCode
44772UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
44773 const UA_NodeId parentNodeId,
44774 const UA_NodeId referenceTypeId,
44775 const UA_QualifiedName browseName,
44776 const UA_MethodAttributes attr, UA_MethodCallback method,
44777 size_t inputArgumentsSize, const UA_Argument *inputArguments,
44778 const UA_NodeId inputArgumentsRequestedNewNodeId,
44779 UA_NodeId *inputArgumentsOutNewNodeId,
44780 size_t outputArgumentsSize, const UA_Argument *outputArguments,
44781 const UA_NodeId outputArgumentsRequestedNewNodeId,
44782 UA_NodeId *outputArgumentsOutNewNodeId,
44783 void *nodeContext, UA_NodeId *outNewNodeId) {
44784 UA_AddNodesItem item;
44785 UA_AddNodesItem_init(p: &item);
44786 item.nodeClass = UA_NODECLASS_METHOD;
44787 item.requestedNewNodeId.nodeId = requestedNewNodeId;
44788 item.browseName = browseName;
44789 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, p: (void*)(uintptr_t)&attr,
44790 type: &UA_TYPES[UA_TYPES_METHODATTRIBUTES]);
44791 UA_NodeId newId;
44792 if(!outNewNodeId) {
44793 UA_NodeId_init(p: &newId);
44794 outNewNodeId = &newId;
44795 }
44796 UA_LOCK(&server->serviceMutex);
44797 UA_StatusCode retval = Operation_addNode_begin(server, session: &server->adminSession,
44798 nodeContext, item: &item, parentNodeId: &parentNodeId,
44799 referenceTypeId: &referenceTypeId, outNewNodeId);
44800 if(retval != UA_STATUSCODE_GOOD) {
44801 UA_UNLOCK(&server->serviceMutex);
44802 return retval;
44803 }
44804
44805 retval = UA_Server_addMethodNodeEx_finish(server, nodeId: *outNewNodeId, method,
44806 inputArgumentsSize, inputArguments,
44807 inputArgumentsRequestedNewNodeId,
44808 inputArgumentsOutNewNodeId,
44809 outputArgumentsSize, outputArguments,
44810 outputArgumentsRequestedNewNodeId,
44811 outputArgumentsOutNewNodeId);
44812 UA_UNLOCK(&server->serviceMutex);
44813 if(outNewNodeId == &newId)
44814 UA_NodeId_clear(p: &newId);
44815 return retval;
44816}
44817
44818static UA_StatusCode
44819editMethodCallback(UA_Server *server, UA_Session* session,
44820 UA_Node *node, UA_MethodCallback methodCallback) {
44821 if(node->head.nodeClass != UA_NODECLASS_METHOD)
44822 return UA_STATUSCODE_BADNODECLASSINVALID;
44823 node->methodNode.method = methodCallback;
44824 return UA_STATUSCODE_GOOD;
44825}
44826
44827static UA_StatusCode
44828setMethodNode_callback(UA_Server *server,
44829 const UA_NodeId methodNodeId,
44830 UA_MethodCallback methodCallback) {
44831 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44832 return UA_Server_editNode(server, session: &server->adminSession, nodeId: &methodNodeId,
44833 callback: (UA_EditNodeCallback)editMethodCallback,
44834 data: (void*)(uintptr_t)methodCallback);
44835}
44836
44837UA_StatusCode
44838UA_Server_setMethodNodeCallback(UA_Server *server,
44839 const UA_NodeId methodNodeId,
44840 UA_MethodCallback methodCallback) {
44841 UA_LOCK(&server->serviceMutex);
44842 UA_StatusCode retVal = setMethodNode_callback(server, methodNodeId, methodCallback);
44843 UA_UNLOCK(&server->serviceMutex);
44844 return retVal;
44845}
44846
44847UA_StatusCode
44848UA_Server_getMethodNodeCallback(UA_Server *server,
44849 const UA_NodeId methodNodeId,
44850 UA_MethodCallback *outMethodCallback) {
44851 UA_LOCK(&server->serviceMutex);
44852 const UA_Node *node = UA_NODESTORE_GET(server, &methodNodeId);
44853 if(!node) {
44854 UA_UNLOCK(&server->serviceMutex);
44855 return UA_STATUSCODE_BADNODEIDUNKNOWN;
44856 }
44857
44858 if(node->head.nodeClass != UA_NODECLASS_METHOD) {
44859 UA_NODESTORE_RELEASE(server, node);
44860 UA_UNLOCK(&server->serviceMutex);
44861 return UA_STATUSCODE_BADNODECLASSINVALID;
44862 }
44863
44864 *outMethodCallback = node->methodNode.method;
44865 UA_NODESTORE_RELEASE(server, node);
44866 UA_UNLOCK(&server->serviceMutex);
44867 return UA_STATUSCODE_GOOD;
44868}
44869
44870#endif
44871
44872/************************/
44873/* Lifecycle Management */
44874/************************/
44875
44876void UA_EXPORT
44877UA_Server_setAdminSessionContext(UA_Server *server,
44878 void *context) {
44879 server->adminSession.sessionHandle = context;
44880}
44881
44882static UA_StatusCode
44883setNodeTypeLifecycle(UA_Server *server, UA_Session *session,
44884 UA_Node *node, UA_NodeTypeLifecycle *lifecycle) {
44885 if(node->head.nodeClass == UA_NODECLASS_OBJECTTYPE) {
44886 node->objectTypeNode.lifecycle = *lifecycle;
44887 } else if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) {
44888 node->variableTypeNode.lifecycle = *lifecycle;
44889 } else {
44890 return UA_STATUSCODE_BADNODECLASSINVALID;
44891 }
44892 return UA_STATUSCODE_GOOD;
44893}
44894
44895UA_StatusCode
44896UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId,
44897 UA_NodeTypeLifecycle lifecycle) {
44898 UA_LOCK(&server->serviceMutex);
44899 UA_StatusCode retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44900 callback: (UA_EditNodeCallback)setNodeTypeLifecycle,
44901 data: &lifecycle);
44902 UA_UNLOCK(&server->serviceMutex);
44903 return retval;
44904}
44905
44906/**** amalgamated original file "/src/server/ua_services_discovery_multicast.c" ****/
44907
44908/* This Source Code Form is subject to the terms of the Mozilla Public
44909 * License, v. 2.0. If a copy of the MPL was not distributed with this
44910 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
44911 *
44912 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
44913 * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
44914 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
44915 */
44916
44917
44918#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
44919
44920#if UA_MULTITHREADING >= 100
44921
44922static void *
44923multicastWorkerLoop(UA_Server *server) {
44924 struct timeval next_sleep = {.tv_sec = 0, .tv_usec = 0};
44925 volatile UA_Boolean *running = &server->discoveryManager.mdnsRunning;
44926 fd_set fds;
44927
44928 while(*running) {
44929 FD_ZERO(&fds);
44930 UA_fd_set(server->discoveryManager.mdnsSocket, &fds);
44931 select(server->discoveryManager.mdnsSocket + 1, &fds, 0, 0, &next_sleep);
44932
44933 if(!*running)
44934 break;
44935
44936 unsigned short retVal =
44937 mdnsd_step(server->discoveryManager.mdnsDaemon, server->discoveryManager.mdnsSocket,
44938 FD_ISSET(server->discoveryManager.mdnsSocket, &fds), true, &next_sleep);
44939 if(retVal == 1) {
44940 UA_LOG_SOCKET_ERRNO_WRAP(
44941 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
44942 "Multicast error: Can not read from socket. %s", errno_str));
44943 break;
44944 } else if (retVal == 2) {
44945 UA_LOG_SOCKET_ERRNO_WRAP(
44946 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
44947 "Multicast error: Can not write to socket. %s", errno_str));
44948 break;
44949 }
44950 }
44951 return NULL;
44952}
44953
44954static UA_StatusCode
44955multicastListenStart(UA_Server* server) {
44956 int err = pthread_create(&server->discoveryManager.mdnsThread, NULL,
44957 (void* (*)(void*))multicastWorkerLoop, server);
44958 if(err != 0) {
44959 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
44960 "Multicast error: Can not create multicast thread.");
44961 return UA_STATUSCODE_BADUNEXPECTEDERROR;
44962 }
44963 return UA_STATUSCODE_GOOD;
44964}
44965
44966static UA_StatusCode
44967multicastListenStop(UA_Server* server) {
44968 mdnsd_shutdown(server->discoveryManager.mdnsDaemon);
44969 // wake up select
44970 if (write(server->discoveryManager.mdnsSocket, "\0", 1)) {
44971 // TODO: if makes no sense here?
44972 } // TODO: move to arch?
44973 if (pthread_join(server->discoveryManager.mdnsThread, NULL)) {
44974 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Multicast error: Can not stop thread.");
44975 return UA_STATUSCODE_BADUNEXPECTEDERROR;
44976 }
44977 return UA_STATUSCODE_BADNOTIMPLEMENTED;
44978}
44979
44980# endif /* UA_MULTITHREADING */
44981
44982static UA_StatusCode
44983addMdnsRecordForNetworkLayer(UA_Server *server, const UA_String *appName,
44984 const UA_ServerNetworkLayer* nl) {
44985 UA_String hostname = UA_STRING_NULL;
44986 UA_UInt16 port = 4840;
44987 UA_String path = UA_STRING_NULL;
44988 UA_StatusCode retval = UA_parseEndpointUrl(&nl->discoveryUrl, &hostname,
44989 &port, &path);
44990 if(retval != UA_STATUSCODE_GOOD) {
44991 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_NETWORK,
44992 "Server url is invalid: %.*s",
44993 (int)nl->discoveryUrl.length, nl->discoveryUrl.data);
44994 return retval;
44995 }
44996
44997 retval = UA_Discovery_addRecord(server, appName, &hostname, port,
44998 &path, UA_DISCOVERY_TCP, true,
44999 server->config.mdnsConfig.serverCapabilities,
45000 server->config.mdnsConfig.serverCapabilitiesSize,
45001 true);
45002 if(retval != UA_STATUSCODE_GOOD) {
45003 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_NETWORK,
45004 "Cannot add mDNS Record: %s",
45005 UA_StatusCode_name(retval));
45006 return retval;
45007 }
45008 return UA_STATUSCODE_GOOD;
45009}
45010
45011void startMulticastDiscoveryServer(UA_Server *server) {
45012 initMulticastDiscoveryServer(&server->discoveryManager, server);
45013
45014 UA_String *appName = &server->config.mdnsConfig.mdnsServerName;
45015 for(size_t i = 0; i < server->config.networkLayersSize; i++)
45016 addMdnsRecordForNetworkLayer(server, appName, &server->config.networkLayers[i]);
45017
45018 /* find any other server on the net */
45019 UA_Discovery_multicastQuery(server);
45020
45021#if UA_MULTITHREADING >= 100
45022 multicastListenStart(server);
45023# endif
45024}
45025
45026void
45027stopMulticastDiscoveryServer(UA_Server *server) {
45028 if (!server->discoveryManager.mdnsDaemon)
45029 return;
45030
45031 for (size_t i=0; i<server->config.networkLayersSize; i++) {
45032
45033 UA_String hostname = UA_STRING_NULL;
45034 UA_String path = UA_STRING_NULL;
45035 UA_UInt16 port = 0;
45036
45037 UA_StatusCode retval = UA_parseEndpointUrl(&server->config.networkLayers[i].discoveryUrl, &hostname,
45038 &port, &path);
45039
45040 if (retval != UA_STATUSCODE_GOOD)
45041 continue;
45042
45043 UA_Discovery_removeRecord(server, &server->config.mdnsConfig.mdnsServerName,
45044 &hostname, port, true);
45045
45046 }
45047
45048#if UA_MULTITHREADING >= 100
45049 multicastListenStop(server);
45050# else
45051 // send out last package with TTL = 0
45052 iterateMulticastDiscoveryServer(server, NULL, false);
45053# endif
45054}
45055
45056/* All filter criteria must be fulfilled in the list entry. The comparison is case
45057 * insensitive.
45058 * @returns true if the entry matches the filter. False if the filter does not match.
45059 * */
45060static UA_Boolean
45061entryMatchesCapabilityFilter(size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter,
45062 serverOnNetwork_list_entry* current) {
45063 // if the entry has less capabilities defined than the filter, there's no match
45064 if (serverCapabilityFilterSize > current->serverOnNetwork.serverCapabilitiesSize)
45065 return UA_FALSE;
45066 for(size_t i = 0; i < serverCapabilityFilterSize; i++) {
45067 UA_Boolean capabilityFound = UA_FALSE;
45068 for(size_t j = 0; j < current->serverOnNetwork.serverCapabilitiesSize; j++) {
45069 if(UA_String_equal_ignorecase(&serverCapabilityFilter[i],
45070 &current->serverOnNetwork.serverCapabilities[j])) {
45071 capabilityFound = UA_TRUE;
45072 break;
45073 }
45074 }
45075 if (!capabilityFound)
45076 return UA_FALSE; // entry does not match capability
45077 }
45078 return UA_TRUE;
45079}
45080
45081void Service_FindServersOnNetwork(UA_Server *server, UA_Session *session,
45082 const UA_FindServersOnNetworkRequest *request,
45083 UA_FindServersOnNetworkResponse *response) {
45084 UA_LOCK_ASSERT(&server->serviceMutex, 1);
45085
45086 if (!server->config.mdnsEnabled) {
45087 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTIMPLEMENTED;
45088 return;
45089 }
45090
45091 /* Set LastCounterResetTime */
45092 UA_DateTime_copy(&server->discoveryManager.serverOnNetworkRecordIdLastReset,
45093 &response->lastCounterResetTime);
45094
45095 /* Compute the max number of records to return */
45096 UA_UInt32 recordCount = 0;
45097 if(request->startingRecordId < server->discoveryManager.serverOnNetworkRecordIdCounter)
45098 recordCount = server->discoveryManager.serverOnNetworkRecordIdCounter -
45099 request->startingRecordId;
45100 if(request->maxRecordsToReturn && recordCount > request->maxRecordsToReturn)
45101 recordCount = UA_MIN(recordCount, request->maxRecordsToReturn);
45102 if(recordCount == 0) {
45103 response->serversSize = 0;
45104 return;
45105 }
45106
45107 /* Iterate over all records and add to filtered list */
45108 UA_UInt32 filteredCount = 0;
45109 UA_STACKARRAY(UA_ServerOnNetwork*, filtered, recordCount);
45110 serverOnNetwork_list_entry* current;
45111 LIST_FOREACH(current, &server->discoveryManager.serverOnNetwork, pointers) {
45112 if(filteredCount >= recordCount)
45113 break;
45114 if(current->serverOnNetwork.recordId < request->startingRecordId)
45115 continue;
45116 if(!entryMatchesCapabilityFilter(request->serverCapabilityFilterSize,
45117 request->serverCapabilityFilter, current))
45118 continue;
45119 filtered[filteredCount++] = &current->serverOnNetwork;
45120 }
45121
45122 if(filteredCount == 0)
45123 return;
45124
45125 /* Allocate the array for the response */
45126 response->servers =
45127 (UA_ServerOnNetwork*)UA_malloc(sizeof(UA_ServerOnNetwork)*filteredCount);
45128 if(!response->servers) {
45129 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
45130 return;
45131 }
45132 response->serversSize = filteredCount;
45133
45134 /* Copy the server names */
45135 for(size_t i = 0; i < filteredCount; i++)
45136 UA_ServerOnNetwork_copy(filtered[i], &response->servers[filteredCount-i-1]);
45137}
45138
45139void
45140UA_Server_updateMdnsForDiscoveryUrl(UA_Server *server, const UA_String *serverName,
45141 const UA_MdnsDiscoveryConfiguration *mdnsConfig,
45142 const UA_String *discoveryUrl,
45143 UA_Boolean isOnline, UA_Boolean updateTxt) {
45144 UA_String hostname = UA_STRING_NULL;
45145 UA_UInt16 port = 4840;
45146 UA_String path = UA_STRING_NULL;
45147 UA_StatusCode retval = UA_parseEndpointUrl(discoveryUrl, &hostname, &port, &path);
45148 if(retval != UA_STATUSCODE_GOOD) {
45149 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_NETWORK,
45150 "Server url invalid: %.*s",
45151 (int)discoveryUrl->length, discoveryUrl->data);
45152 return;
45153 }
45154
45155 if(!isOnline) {
45156 UA_StatusCode removeRetval =
45157 UA_Discovery_removeRecord(server, serverName, &hostname,
45158 port, updateTxt);
45159 if(removeRetval != UA_STATUSCODE_GOOD)
45160 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45161 "Could not remove mDNS record for hostname %.*s.",
45162 (int)serverName->length, serverName->data);
45163 return;
45164 }
45165
45166 UA_String *capabilities = NULL;
45167 size_t capabilitiesSize = 0;
45168 if(mdnsConfig) {
45169 capabilities = mdnsConfig->serverCapabilities;
45170 capabilitiesSize = mdnsConfig->serverCapabilitiesSize;
45171 }
45172
45173 UA_StatusCode addRetval =
45174 UA_Discovery_addRecord(server, serverName, &hostname,
45175 port, &path, UA_DISCOVERY_TCP, updateTxt,
45176 capabilities, capabilitiesSize,
45177 false);
45178 if(addRetval != UA_STATUSCODE_GOOD)
45179 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45180 "Could not add mDNS record for hostname %.*s.",
45181 (int)serverName->length, serverName->data);
45182}
45183
45184void
45185UA_Server_setServerOnNetworkCallback(UA_Server *server,
45186 UA_Server_serverOnNetworkCallback cb,
45187 void* data) {
45188 UA_LOCK(&server->serviceMutex);
45189 server->discoveryManager.serverOnNetworkCallback = cb;
45190 server->discoveryManager.serverOnNetworkCallbackData = data;
45191 UA_UNLOCK(&server->serviceMutex);
45192}
45193
45194static void
45195UA_Discovery_multicastConflict(char *name, int type, void *arg) {
45196 // cppcheck-suppress unreadVariable
45197 UA_Server *server = (UA_Server*) arg;
45198 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
45199 "Multicast DNS name conflict detected: "
45200 "'%s' for type %d", name, type);
45201}
45202
45203/* Create a service domain with the format [servername]-[hostname]._opcua-tcp._tcp.local. */
45204static void
45205createFullServiceDomain(char *outServiceDomain, size_t maxLen,
45206 const UA_String *servername, const UA_String *hostname) {
45207 size_t hostnameLen = hostname->length;
45208 size_t servernameLen = servername->length;
45209
45210 maxLen -= 24; /* the length we have remaining before the opc ua postfix and
45211 * the trailing zero */
45212
45213 /* Can we use hostname and servername with full length? */
45214 if(hostnameLen + servernameLen + 1 > maxLen) {
45215 if(servernameLen + 2 > maxLen) {
45216 servernameLen = maxLen;
45217 hostnameLen = 0;
45218 } else {
45219 hostnameLen = maxLen - servernameLen - 1;
45220 }
45221 }
45222
45223 size_t offset = 0;
45224 if (hostnameLen > 0) {
45225 UA_snprintf(outServiceDomain, maxLen + 1, "%.*s-%.*s",
45226 (int) servernameLen, (char *) servername->data,
45227 (int) hostnameLen, (char *) hostname->data);
45228 offset = servernameLen + hostnameLen + 1;
45229 //replace all dots with minus. Otherwise mDNS is not valid
45230 for (size_t i=servernameLen+1; i<offset; i++) {
45231 if (outServiceDomain[i] == '.')
45232 outServiceDomain[i] = '-';
45233 }
45234 }
45235 else {
45236 UA_snprintf(outServiceDomain, maxLen + 1, "%.*s",
45237 (int) servernameLen, (char *) servername->data);
45238 offset = servernameLen;
45239 }
45240 UA_snprintf(&outServiceDomain[offset], 24, "._opcua-tcp._tcp.local.");
45241}
45242
45243/* Check if mDNS already has an entry for given hostname and port combination */
45244static UA_Boolean
45245UA_Discovery_recordExists(UA_Server* server, const char* fullServiceDomain,
45246 unsigned short port, const UA_DiscoveryProtocol protocol) {
45247 // [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port [hostname].
45248 mdns_record_t *r = mdnsd_get_published(server->discoveryManager.mdnsDaemon, fullServiceDomain);
45249 while(r) {
45250 const mdns_answer_t *data = mdnsd_record_data(r);
45251 if(data->type == QTYPE_SRV && (port == 0 || data->srv.port == port))
45252 return true;
45253 r = mdnsd_record_next(r);
45254 }
45255 return false;
45256}
45257
45258static int
45259discovery_multicastQueryAnswer(mdns_answer_t *a, void *arg) {
45260 UA_Server *server = (UA_Server*) arg;
45261 if(a->type != QTYPE_PTR)
45262 return 0;
45263
45264 if(a->rdname == NULL)
45265 return 0;
45266
45267 /* Skip, if we already know about this server */
45268 UA_Boolean exists =
45269 UA_Discovery_recordExists(server, a->rdname, 0, UA_DISCOVERY_TCP);
45270 if(exists == true)
45271 return 0;
45272
45273 if(mdnsd_has_query(server->discoveryManager.mdnsDaemon, a->rdname))
45274 return 0;
45275
45276 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
45277 "mDNS send query for: %s SRV&TXT %s", a->name, a->rdname);
45278
45279 mdnsd_query(server->discoveryManager.mdnsDaemon, a->rdname, QTYPE_SRV,
45280 discovery_multicastQueryAnswer, server);
45281 mdnsd_query(server->discoveryManager.mdnsDaemon, a->rdname, QTYPE_TXT,
45282 discovery_multicastQueryAnswer, server);
45283 return 0;
45284}
45285
45286UA_StatusCode
45287UA_Discovery_multicastQuery(UA_Server* server) {
45288 mdnsd_query(server->discoveryManager.mdnsDaemon, "_opcua-tcp._tcp.local.",
45289 QTYPE_PTR,discovery_multicastQueryAnswer, server);
45290 return UA_STATUSCODE_GOOD;
45291}
45292
45293UA_StatusCode
45294UA_Discovery_addRecord(UA_Server *server, const UA_String *servername,
45295 const UA_String *hostname, UA_UInt16 port,
45296 const UA_String *path, const UA_DiscoveryProtocol protocol,
45297 UA_Boolean createTxt, const UA_String* capabilites,
45298 const size_t capabilitiesSize,
45299 UA_Boolean isSelf) {
45300 // we assume that the hostname is not an IP address, but a valid domain name
45301 // It is required by the OPC UA spec (see Part 12, DiscoveryURL to DNS SRV mapping)
45302 // to always use the hostname instead of the IP address
45303
45304 if(capabilitiesSize > 0 && !capabilites)
45305 return UA_STATUSCODE_BADINVALIDARGUMENT;
45306
45307 size_t hostnameLen = hostname->length;
45308 size_t servernameLen = servername->length;
45309 if(hostnameLen == 0 || servernameLen == 0)
45310 return UA_STATUSCODE_BADOUTOFRANGE;
45311
45312 // use a limit for the hostname length to make sure full string fits into 63
45313 // chars (limited by DNS spec)
45314 if(hostnameLen+servernameLen + 1 > 63) { // include dash between servername-hostname
45315 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45316 "Multicast DNS: Combination of hostname+servername exceeds "
45317 "maximum of 62 chars. It will be truncated.");
45318 } else if(hostnameLen > 63) {
45319 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45320 "Multicast DNS: Hostname length exceeds maximum of 63 chars. "
45321 "It will be truncated.");
45322 }
45323
45324 if(!server->discoveryManager.mdnsMainSrvAdded) {
45325 mdns_record_t *r =
45326 mdnsd_shared(server->discoveryManager.mdnsDaemon, "_services._dns-sd._udp.local.",
45327 QTYPE_PTR, 600);
45328 mdnsd_set_host(server->discoveryManager.mdnsDaemon, r, "_opcua-tcp._tcp.local.");
45329 server->discoveryManager.mdnsMainSrvAdded = true;
45330 }
45331
45332 // [servername]-[hostname]._opcua-tcp._tcp.local.
45333 char fullServiceDomain[63+24];
45334 createFullServiceDomain(fullServiceDomain, 63+24, servername, hostname);
45335
45336 UA_Boolean exists = UA_Discovery_recordExists(server, fullServiceDomain, port, protocol);
45337 if(exists == true)
45338 return UA_STATUSCODE_GOOD;
45339
45340 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
45341 "Multicast DNS: add record for domain: %s", fullServiceDomain);
45342
45343
45344 if (isSelf && server->discoveryManager.selfFqdnMdnsRecord.length == 0) {
45345 server->discoveryManager.selfFqdnMdnsRecord = UA_STRING_ALLOC(fullServiceDomain);
45346 if (!server->discoveryManager.selfFqdnMdnsRecord.data)
45347 return UA_STATUSCODE_BADOUTOFMEMORY;
45348 }
45349
45350
45351 struct serverOnNetwork_list_entry *listEntry;
45352 // The servername is servername + hostname. It is the same which we get through mDNS and therefore we need to match servername
45353 UA_StatusCode retval = UA_DiscoveryManager_addEntryToServersOnNetwork(server, fullServiceDomain, fullServiceDomain,
45354 UA_MIN(63, (servernameLen+hostnameLen)+1), &listEntry);
45355 if (retval != UA_STATUSCODE_GOOD && retval != UA_STATUSCODE_BADALREADYEXISTS)
45356 return retval;
45357
45358 // If entry is already in list, skip initialization of capabilities and txt+srv
45359 if (retval != UA_STATUSCODE_BADALREADYEXISTS) {
45360 // if capabilitiesSize is 0, then add default cap 'NA'
45361 listEntry->serverOnNetwork.serverCapabilitiesSize = UA_MAX(1, capabilitiesSize);
45362 listEntry->serverOnNetwork.serverCapabilities =
45363 (UA_String *) UA_Array_new(listEntry->serverOnNetwork.serverCapabilitiesSize, &UA_TYPES[UA_TYPES_STRING]);
45364 if (!listEntry->serverOnNetwork.serverCapabilities)
45365 return UA_STATUSCODE_BADOUTOFMEMORY;
45366 if (capabilitiesSize == 0) {
45367 UA_String na;
45368 na.length = 2;
45369 na.data = (UA_Byte *) (uintptr_t) "NA";
45370 UA_String_copy(&na, &listEntry->serverOnNetwork.serverCapabilities[0]);
45371 } else {
45372 for (size_t i = 0; i < capabilitiesSize; i++) {
45373 UA_String_copy(&capabilites[i], &listEntry->serverOnNetwork.serverCapabilities[i]);
45374 }
45375 }
45376
45377 listEntry->txtSet = true;
45378
45379 UA_STACKARRAY(char, newUrl, 10 + hostnameLen + 8 + path->length + 1);
45380 UA_snprintf(newUrl, 10 + hostnameLen + 8 + path->length + 1, "opc.tcp://%.*s:%d%s%.*s", (int) hostnameLen,
45381 hostname->data, port, path->length > 0 ? "/" : "", (int) path->length, path->data);
45382 listEntry->serverOnNetwork.discoveryUrl = UA_String_fromChars(newUrl);
45383 listEntry->srvSet = true;
45384 }
45385
45386 // _services._dns-sd._udp.local. PTR _opcua-tcp._tcp.local
45387
45388 // check if there is already a PTR entry for the given service.
45389
45390 // _opcua-tcp._tcp.local. PTR [servername]-[hostname]._opcua-tcp._tcp.local.
45391 mdns_record_t *r = mdns_find_record(server->discoveryManager.mdnsDaemon, QTYPE_PTR,
45392 "_opcua-tcp._tcp.local.", fullServiceDomain);
45393 if(!r) {
45394 r = mdnsd_shared(server->discoveryManager.mdnsDaemon, "_opcua-tcp._tcp.local.", QTYPE_PTR, 600);
45395 mdnsd_set_host(server->discoveryManager.mdnsDaemon, r, fullServiceDomain);
45396 }
45397
45398 /* The first 63 characters of the hostname (or less) */
45399 size_t maxHostnameLen = UA_MIN(hostnameLen, 63);
45400 char localDomain[65];
45401 memcpy(localDomain, hostname->data, maxHostnameLen);
45402 localDomain[maxHostnameLen] = '.';
45403 localDomain[maxHostnameLen+1] = '\0';
45404
45405 // [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port [hostname].
45406 r = mdnsd_unique(server->discoveryManager.mdnsDaemon, fullServiceDomain, QTYPE_SRV, 600,
45407 UA_Discovery_multicastConflict, server);
45408 mdnsd_set_srv(server->discoveryManager.mdnsDaemon, r, 0, 0, port, localDomain);
45409
45410 // A/AAAA record for all ip addresses.
45411 // [servername]-[hostname]._opcua-tcp._tcp.local. A [ip].
45412 // [hostname]. A [ip].
45413 mdns_set_address_record(server, fullServiceDomain, localDomain);
45414
45415 // TXT record: [servername]-[hostname]._opcua-tcp._tcp.local. TXT path=/ caps=NA,DA,...
45416 UA_STACKARRAY(char, pathChars, path->length + 1);
45417 if(createTxt) {
45418 if(path->length > 0)
45419 memcpy(pathChars, path->data, path->length);
45420 pathChars[path->length] = 0;
45421 mdns_create_txt(server, fullServiceDomain, pathChars, capabilites,
45422 capabilitiesSize, UA_Discovery_multicastConflict);
45423 }
45424
45425 return UA_STATUSCODE_GOOD;
45426}
45427
45428UA_StatusCode
45429UA_Discovery_removeRecord(UA_Server *server, const UA_String *servername,
45430 const UA_String *hostname, UA_UInt16 port,
45431 UA_Boolean removeTxt) {
45432 // use a limit for the hostname length to make sure full string fits into 63
45433 // chars (limited by DNS spec)
45434 size_t hostnameLen = hostname->length;
45435 size_t servernameLen = servername->length;
45436 if(hostnameLen == 0 || servernameLen == 0)
45437 return UA_STATUSCODE_BADOUTOFRANGE;
45438
45439 if(hostnameLen+servernameLen+1 > 63) { // include dash between servername-hostname
45440 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45441 "Multicast DNS: Combination of hostname+servername exceeds "
45442 "maximum of 62 chars. It will be truncated.");
45443 }
45444
45445 // [servername]-[hostname]._opcua-tcp._tcp.local.
45446 char fullServiceDomain[63 + 24];
45447 createFullServiceDomain(fullServiceDomain, 63+24, servername, hostname);
45448
45449 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
45450 "Multicast DNS: remove record for domain: %s", fullServiceDomain);
45451
45452 UA_StatusCode retval = UA_DiscoveryManager_removeEntryFromServersOnNetwork(
45453 server, fullServiceDomain, fullServiceDomain, UA_MIN(63, (servernameLen+hostnameLen)+1));
45454 if (retval != UA_STATUSCODE_GOOD)
45455 return retval;
45456
45457 // _opcua-tcp._tcp.local. PTR [servername]-[hostname]._opcua-tcp._tcp.local.
45458 mdns_record_t *r = mdns_find_record(server->discoveryManager.mdnsDaemon, QTYPE_PTR,
45459 "_opcua-tcp._tcp.local.", fullServiceDomain);
45460 if(!r) {
45461 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45462 "Multicast DNS: could not remove record. "
45463 "PTR Record not found for domain: %s", fullServiceDomain);
45464 return UA_STATUSCODE_BADNOTHINGTODO;
45465 }
45466 mdnsd_done(server->discoveryManager.mdnsDaemon, r);
45467
45468 // looks for [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port hostname.local.
45469 // and TXT record: [servername]-[hostname]._opcua-tcp._tcp.local. TXT path=/ caps=NA,DA,...
45470 // and A record: [servername]-[hostname]._opcua-tcp._tcp.local. A [ip]
45471 mdns_record_t *r2 = mdnsd_get_published(server->discoveryManager.mdnsDaemon, fullServiceDomain);
45472 if(!r2) {
45473 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45474 "Multicast DNS: could not remove record. Record not "
45475 "found for domain: %s", fullServiceDomain);
45476 return UA_STATUSCODE_BADNOTHINGTODO;
45477 }
45478
45479 while(r2) {
45480 const mdns_answer_t *data = mdnsd_record_data(r2);
45481 mdns_record_t *next = mdnsd_record_next(r2);
45482 if((removeTxt && data->type == QTYPE_TXT) ||
45483 (removeTxt && data->type == QTYPE_A) ||
45484 data->srv.port == port) {
45485 mdnsd_done(server->discoveryManager.mdnsDaemon, r2);
45486 }
45487 r2 = next;
45488 }
45489
45490 return UA_STATUSCODE_GOOD;
45491}
45492
45493UA_StatusCode
45494iterateMulticastDiscoveryServer(UA_Server* server, UA_DateTime *nextRepeat,
45495 UA_Boolean processIn) {
45496 struct timeval next_sleep = { 0, 0 };
45497 unsigned short retval = mdnsd_step(server->discoveryManager.mdnsDaemon,
45498 (int)server->discoveryManager.mdnsSocket,
45499 processIn, true, &next_sleep);
45500 if(retval == 1) {
45501 UA_LOG_SOCKET_ERRNO_WRAP(
45502 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
45503 "Multicast error: Can not read from socket. %s", errno_str));
45504 return UA_STATUSCODE_BADNOCOMMUNICATION;
45505 } else if(retval == 2) {
45506 UA_LOG_SOCKET_ERRNO_WRAP(
45507 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
45508 "Multicast error: Can not write to socket. %s", errno_str));
45509 return UA_STATUSCODE_BADNOCOMMUNICATION;
45510 }
45511
45512 if(nextRepeat)
45513 *nextRepeat = UA_DateTime_now() +
45514 (UA_DateTime)((next_sleep.tv_sec * UA_DATETIME_SEC) +
45515 (next_sleep.tv_usec * UA_DATETIME_USEC));
45516 return UA_STATUSCODE_GOOD;
45517}
45518
45519#endif /* defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST) */
45520
45521/**** amalgamated original file "/src/client/ua_client.c" ****/
45522
45523/* This Source Code Form is subject to the terms of the Mozilla Public
45524 * License, v. 2.0. If a copy of the MPL was not distributed with this
45525 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
45526 *
45527 * Copyright 2015-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
45528 * Copyright 2015-2016 (c) Sten Grüner
45529 * Copyright 2015-2016 (c) Chris Iatrou
45530 * Copyright 2015 (c) hfaham
45531 * Copyright 2015-2017 (c) Florian Palm
45532 * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
45533 * Copyright 2015 (c) Holger Jeromin
45534 * Copyright 2015 (c) Oleksiy Vasylyev
45535 * Copyright 2016 (c) TorbenD
45536 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
45537 * Copyright 2016 (c) Lykurg
45538 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
45539 * Copyright 2018 (c) Kalycito Infotech Private Limited
45540 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart
45541 */
45542
45543
45544
45545/********************/
45546/* Client Lifecycle */
45547/********************/
45548
45549static void
45550UA_Client_init(UA_Client* client) {
45551 UA_SecureChannel_init(channel: &client->channel, config: &client->config.localConnectionConfig);
45552 client->connectStatus = UA_STATUSCODE_GOOD;
45553 UA_Timer_init(t: &client->timer);
45554 notifyClientState(client);
45555}
45556
45557UA_Client UA_EXPORT *
45558UA_Client_newWithConfig(const UA_ClientConfig *config) {
45559 if(!config)
45560 return NULL;
45561 UA_Client *client = (UA_Client*)UA_malloc(size: sizeof(UA_Client));
45562 if(!client)
45563 return NULL;
45564 memset(s: client, c: 0, n: sizeof(UA_Client));
45565 client->config = *config;
45566 UA_Client_init(client);
45567 return client;
45568}
45569
45570static void
45571UA_ClientConfig_clear(UA_ClientConfig *config) {
45572 UA_ApplicationDescription_clear(p: &config->clientDescription);
45573
45574 UA_ExtensionObject_clear(p: &config->userIdentityToken);
45575 UA_String_clear(p: &config->securityPolicyUri);
45576
45577 UA_EndpointDescription_clear(p: &config->endpoint);
45578 UA_UserTokenPolicy_clear(p: &config->userTokenPolicy);
45579
45580 UA_String_clear(p: &config->applicationUri);
45581
45582 if(config->certificateVerification.clear)
45583 config->certificateVerification.clear(&config->certificateVerification);
45584
45585 /* Delete the SecurityPolicies */
45586 if(config->securityPolicies == 0)
45587 return;
45588 for(size_t i = 0; i < config->securityPoliciesSize; i++)
45589 config->securityPolicies[i].clear(&config->securityPolicies[i]);
45590 UA_free(ptr: config->securityPolicies);
45591 config->securityPolicies = 0;
45592
45593 /* Logger */
45594 if(config->logger.clear)
45595 config->logger.clear(config->logger.context);
45596 config->logger.log = NULL;
45597 config->logger.clear = NULL;
45598
45599 if (config->sessionLocaleIdsSize > 0 && config->sessionLocaleIds) {
45600 UA_Array_delete(p: config->sessionLocaleIds, size: config->sessionLocaleIdsSize, type: &UA_TYPES[UA_TYPES_LOCALEID]);
45601 }
45602 config->sessionLocaleIds = NULL;
45603 config->sessionLocaleIdsSize = 0;
45604}
45605
45606static void
45607UA_Client_clear(UA_Client *client) {
45608 /* Prevent new async service calls in UA_Client_AsyncService_removeAll */
45609 UA_SessionState oldState = client->sessionState;
45610 client->sessionState = UA_SESSIONSTATE_CLOSING;
45611
45612 /* Delete the async service calls with BADHSUTDOWN */
45613 UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN);
45614
45615 /* Reset to the old state to properly close the session */
45616 client->sessionState = oldState;
45617
45618 UA_Client_disconnect(client);
45619 UA_String_clear(p: &client->endpointUrl);
45620 UA_String_clear(p: &client->discoveryUrl);
45621
45622 UA_String_clear(p: &client->remoteNonce);
45623 UA_String_clear(p: &client->localNonce);
45624
45625 /* Delete the subscriptions */
45626#ifdef UA_ENABLE_SUBSCRIPTIONS
45627 UA_Client_Subscriptions_clean(client);
45628#endif
45629
45630 /* Delete the timed work */
45631 UA_Timer_clear(t: &client->timer);
45632}
45633
45634void
45635UA_Client_delete(UA_Client* client) {
45636 UA_Client_clear(client);
45637 UA_ClientConfig_clear(config: &client->config);
45638 UA_free(ptr: client);
45639}
45640
45641void
45642UA_Client_getState(UA_Client *client, UA_SecureChannelState *channelState,
45643 UA_SessionState *sessionState, UA_StatusCode *connectStatus) {
45644 if(channelState)
45645 *channelState = client->channel.state;
45646 if(sessionState)
45647 *sessionState = client->sessionState;
45648 if(connectStatus)
45649 *connectStatus = client->connectStatus;
45650}
45651
45652UA_ClientConfig *
45653UA_Client_getConfig(UA_Client *client) {
45654 if(!client)
45655 return NULL;
45656 return &client->config;
45657}
45658
45659#if UA_LOGLEVEL <= 300
45660static const char *channelStateTexts[9] = {
45661 "Fresh", "HELSent", "HELReceived", "ACKSent",
45662 "AckReceived", "OPNSent", "Open", "Closing", "Closed"};
45663static const char *sessionStateTexts[6] =
45664 {"Closed", "CreateRequested", "Created",
45665 "ActivateRequested", "Activated", "Closing"};
45666#endif
45667
45668void
45669notifyClientState(UA_Client *client) {
45670 if(client->connectStatus == client->oldConnectStatus &&
45671 client->channel.state == client->oldChannelState &&
45672 client->sessionState == client->oldSessionState)
45673 return;
45674
45675#if UA_LOGLEVEL <= 300
45676 UA_Boolean info = (client->connectStatus != UA_STATUSCODE_GOOD);
45677 if(client->oldChannelState != client->channel.state)
45678 info |= (client->channel.state == UA_SECURECHANNELSTATE_OPEN ||
45679 client->channel.state == UA_SECURECHANNELSTATE_CLOSED);
45680 if(client->oldSessionState != client->sessionState)
45681 info |= (client->sessionState == UA_SESSIONSTATE_CREATED ||
45682 client->sessionState == UA_SESSIONSTATE_ACTIVATED ||
45683 client->sessionState == UA_SESSIONSTATE_CLOSED);
45684
45685 const char *channelStateText = channelStateTexts[client->channel.state];
45686 const char *sessionStateText = sessionStateTexts[client->sessionState];
45687 const char *connectStatusText = UA_StatusCode_name(code: client->connectStatus);
45688
45689 if(info)
45690 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45691 msg: "Client Status: ChannelState: %s, SessionState: %s, ConnectStatus: %s",
45692 channelStateText, sessionStateText, connectStatusText);
45693 else
45694 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45695 msg: "Client Status: ChannelState: %s, SessionState: %s, ConnectStatus: %s",
45696 channelStateText, sessionStateText, connectStatusText);
45697#endif
45698
45699 client->oldConnectStatus = client->connectStatus;
45700 client->oldChannelState = client->channel.state;
45701 client->oldSessionState = client->sessionState;
45702
45703 if(client->config.stateCallback)
45704 client->config.stateCallback(client, client->channel.state,
45705 client->sessionState, client->connectStatus);
45706}
45707
45708/****************/
45709/* Raw Services */
45710/****************/
45711
45712/* For synchronous service calls. Execute async responses with a callback. When
45713 * the response with the correct requestId turns up, return it via the
45714 * SyncResponseDescription pointer. */
45715typedef struct {
45716 UA_Client *client;
45717 UA_Boolean received;
45718 UA_UInt32 requestId;
45719 void *response;
45720 const UA_DataType *responseType;
45721} SyncResponseDescription;
45722
45723/* For both synchronous and asynchronous service calls */
45724static UA_StatusCode
45725sendSymmetricServiceRequest(UA_Client *client, const void *request,
45726 const UA_DataType *requestType, UA_UInt32 *requestId) {
45727 /* Renew SecureChannel if necessary */
45728 UA_Client_renewSecureChannel(client);
45729 if(client->connectStatus != UA_STATUSCODE_GOOD)
45730 return client->connectStatus;
45731
45732 /* Adjusting the request header. The const attribute is violated, but we
45733 * only touch the following members: */
45734 UA_RequestHeader *rr = (UA_RequestHeader*)(uintptr_t)request;
45735 UA_NodeId oldToken = rr->authenticationToken; /* Put back in place later */
45736 rr->authenticationToken = client->authenticationToken;
45737 rr->timestamp = UA_DateTime_now();
45738 rr->requestHandle = ++client->requestHandle;
45739 UA_UInt32 rqId = ++client->requestId;
45740
45741#ifdef UA_ENABLE_TYPEDESCRIPTION
45742 UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
45743 "Sending request with RequestId %u of type %s",
45744 (unsigned)rqId, requestType->typeName);
45745#else
45746 UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
45747 "Sending request with RequestId %u of type %" PRIu32,
45748 (unsigned)rqId, requestType->binaryEncodingId.identifier.numeric);
45749#endif
45750
45751 /* Send the message */
45752 UA_StatusCode retval =
45753 UA_SecureChannel_sendSymmetricMessage(channel: &client->channel, requestId: rqId,
45754 messageType: UA_MESSAGETYPE_MSG, payload: rr, payloadType: requestType);
45755 rr->authenticationToken = oldToken; /* Set the original token */
45756
45757 *requestId = rqId;
45758 return retval;
45759}
45760
45761static const UA_NodeId
45762serviceFaultId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_SERVICEFAULT_ENCODING_DEFAULTBINARY}};
45763
45764/* Look for the async callback in the linked list, execute and delete it */
45765static UA_StatusCode
45766processAsyncResponse(UA_Client *client, UA_UInt32 requestId, const UA_NodeId *responseTypeId,
45767 const UA_ByteString *responseMessage, size_t *offset) {
45768 /* Find the callback */
45769 AsyncServiceCall *ac;
45770 LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) {
45771 if(ac->requestId == requestId)
45772 break;
45773 }
45774
45775 /* Part 6, 6.7.6: After the security validation is complete the receiver
45776 * shall verify the RequestId and the SequenceNumber. If these checks fail a
45777 * Bad_SecurityChecksFailed error is reported. The RequestId only needs to
45778 * be verified by the Client since only the Client knows if it is valid or
45779 * not.*/
45780 if(!ac)
45781 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
45782
45783 /* Dequeue ac. We might disconnect (remove all ac) in the callback. */
45784 LIST_REMOVE(ac, pointers);
45785
45786 /* Verify the type of the response */
45787 UA_Response response;
45788 const UA_DataType *responseType = ac->responseType;
45789 UA_StatusCode retval = UA_STATUSCODE_GOOD;
45790 if(!UA_NodeId_equal(n1: responseTypeId, n2: &ac->responseType->binaryEncodingId)) {
45791 UA_init(p: &response, type: ac->responseType);
45792 if(UA_NodeId_equal(n1: responseTypeId, n2: &serviceFaultId)) {
45793 /* Decode as a ServiceFault, i.e. only the response header */
45794 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45795 msg: "Received a ServiceFault response");
45796 responseType = &UA_TYPES[UA_TYPES_SERVICEFAULT];
45797 } else {
45798 /* Close the connection */
45799 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45800 msg: "Reply contains the wrong service response");
45801 retval = UA_STATUSCODE_BADCOMMUNICATIONERROR;
45802 goto process;
45803 }
45804 }
45805
45806 /* Decode the response */
45807 retval = UA_decodeBinaryInternal(src: responseMessage, offset, dst: &response, type: responseType,
45808 customTypes: client->config.customDataTypes);
45809
45810 process:
45811 if(retval != UA_STATUSCODE_GOOD) {
45812 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45813 msg: "Could not decode the response with id %u due to %s",
45814 (unsigned)requestId, UA_StatusCode_name(code: retval));
45815 response.responseHeader.serviceResult = retval;
45816 } else if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
45817 /* Decode as a ServiceFault, i.e. only the response header */
45818 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45819 msg: "The ServiceResult has the StatusCode %s",
45820 UA_StatusCode_name(code: response.responseHeader.serviceResult));
45821 }
45822
45823 /* Call the callback */
45824 if(ac->callback)
45825 ac->callback(client, ac->userdata, requestId, &response);
45826 UA_clear(p: &response, type: ac->responseType);
45827
45828 /* Remove the callback */
45829 UA_free(ptr: ac);
45830 return retval;
45831}
45832
45833/* Processes the received service response. Either with an async callback or by
45834 * decoding the message and returning it "upwards" in the
45835 * SyncResponseDescription. */
45836static UA_StatusCode
45837processServiceResponse(void *application, UA_SecureChannel *channel,
45838 UA_MessageType messageType, UA_UInt32 requestId,
45839 UA_ByteString *message) {
45840 SyncResponseDescription *rd = (SyncResponseDescription*)application;
45841
45842 /* Process ACK response */
45843 switch(messageType) {
45844 case UA_MESSAGETYPE_ACK:
45845 processACKResponse(client: rd->client, chunk: message);
45846 return UA_STATUSCODE_GOOD;
45847 case UA_MESSAGETYPE_OPN:
45848 processOPNResponse(client: rd->client, message);
45849 return UA_STATUSCODE_GOOD;
45850 case UA_MESSAGETYPE_ERR:
45851 processERRResponse(client: rd->client, chunk: message);
45852 return UA_STATUSCODE_GOOD;
45853 case UA_MESSAGETYPE_MSG:
45854 /* Continue below */
45855 break;
45856 default:
45857 UA_LOG_TRACE_CHANNEL(&rd->client->config.logger, channel, "Invalid message type");
45858 channel->state = UA_SECURECHANNELSTATE_CLOSING;
45859 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
45860 }
45861
45862 /* Decode the data type identifier of the response */
45863 size_t offset = 0;
45864 UA_NodeId responseId;
45865 UA_StatusCode retval = UA_NodeId_decodeBinary(src: message, offset: &offset, dst: &responseId);
45866 if(retval != UA_STATUSCODE_GOOD)
45867 goto finish;
45868
45869 /* Got an asynchronous response. Don't expected a synchronous response
45870 * (responseType NULL) or the id does not match. */
45871 if(!rd->responseType || requestId != rd->requestId) {
45872 retval = processAsyncResponse(client: rd->client, requestId, responseTypeId: &responseId, responseMessage: message, offset: &offset);
45873 goto finish;
45874 }
45875
45876 /* Got the synchronous response */
45877 rd->received = true;
45878
45879 /* Check that the response type matches */
45880 if(!UA_NodeId_equal(n1: &responseId, n2: &rd->responseType->binaryEncodingId)) {
45881 if(UA_NodeId_equal(n1: &responseId, n2: &serviceFaultId)) {
45882 UA_init(p: rd->response, type: rd->responseType);
45883 retval = UA_decodeBinaryInternal(src: message, offset: &offset, dst: rd->response,
45884 type: &UA_TYPES[UA_TYPES_SERVICEFAULT],
45885 customTypes: rd->client->config.customDataTypes);
45886 if(retval != UA_STATUSCODE_GOOD)
45887 ((UA_ResponseHeader*)rd->response)->serviceResult = retval;
45888 UA_LOG_INFO(logger: &rd->client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45889 msg: "Received a ServiceFault response with StatusCode %s",
45890 UA_StatusCode_name(code: ((UA_ResponseHeader*)rd->response)->serviceResult));
45891 } else {
45892 /* Close the connection */
45893 UA_LOG_ERROR(logger: &rd->client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45894 msg: "Reply contains the wrong service response");
45895 retval = UA_STATUSCODE_BADCOMMUNICATIONERROR;
45896 }
45897 goto finish;
45898 }
45899
45900#ifdef UA_ENABLE_TYPEDESCRIPTION
45901 UA_LOG_DEBUG(logger: &rd->client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45902 msg: "Decode a message of type %s", rd->responseType->typeName);
45903#else
45904 UA_LOG_DEBUG(&rd->client->config.logger, UA_LOGCATEGORY_CLIENT,
45905 "Decode a message of type %" PRIu32, responseId.identifier.numeric);
45906#endif
45907
45908 /* Decode the response */
45909 retval = UA_decodeBinaryInternal(src: message, offset: &offset, dst: rd->response, type: rd->responseType,
45910 customTypes: rd->client->config.customDataTypes);
45911
45912finish:
45913 UA_NodeId_clear(p: &responseId);
45914 if(retval != UA_STATUSCODE_GOOD) {
45915 if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
45916 retval = UA_STATUSCODE_BADRESPONSETOOLARGE;
45917 UA_LOG_INFO(logger: &rd->client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45918 msg: "Error receiving the response with status code %s",
45919 UA_StatusCode_name(code: retval));
45920
45921 if(rd->response) {
45922 UA_ResponseHeader *respHeader = (UA_ResponseHeader*)rd->response;
45923 respHeader->serviceResult = retval;
45924 }
45925 }
45926
45927 return retval;
45928}
45929
45930/* Receive and process messages until a synchronous message arrives or the
45931 * timout finishes */
45932static UA_StatusCode
45933receiveResponse(UA_Client *client, void *response, const UA_DataType *responseType,
45934 UA_DateTime maxDate, const UA_UInt32 *synchronousRequestId) {
45935 /* Prepare the response and the structure we give into processServiceResponse */
45936 SyncResponseDescription rd = { client, false, 0, response, responseType };
45937
45938 /* Return upon receiving the synchronized response. All other responses are
45939 * processed with a callback "in the background". */
45940 if(synchronousRequestId)
45941 rd.requestId = *synchronousRequestId;
45942
45943 UA_StatusCode retval = UA_STATUSCODE_GOOD;
45944 UA_DateTime now = UA_DateTime_nowMonotonic();
45945 do {
45946 UA_UInt32 timeout2 = (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC);
45947 if(maxDate < now)
45948 timeout2 = 0;
45949 retval = UA_SecureChannel_receive(channel: &client->channel, application: &rd, callback: processServiceResponse, timeout: timeout2);
45950 if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT)
45951 break;
45952 if(retval != UA_STATUSCODE_GOOD ||
45953 client->channel.state == UA_SECURECHANNELSTATE_CLOSING) {
45954 UA_LOG_WARNING_CHANNEL(&client->config.logger, &client->channel,
45955 "Receiving the response failed with StatusCode %s",
45956 UA_StatusCode_name(retval));
45957 closeSecureChannel(client);
45958 retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
45959 break;
45960 }
45961 now = UA_DateTime_nowMonotonic();
45962 if(maxDate < now)
45963 break;
45964 } while(!rd.received && responseType); /* Return if we don't wait for an async response */
45965
45966 return retval;
45967}
45968
45969UA_StatusCode
45970receiveResponseAsync(UA_Client *client, UA_UInt32 timeout) {
45971 UA_DateTime maxDate = UA_DateTime_nowMonotonic() + ((UA_DateTime)timeout * UA_DATETIME_MSEC);
45972 UA_StatusCode res = receiveResponse(client, NULL, NULL, maxDate, NULL);
45973 return (res != UA_STATUSCODE_GOODNONCRITICALTIMEOUT) ? res : UA_STATUSCODE_GOOD;
45974}
45975
45976void
45977__UA_Client_Service(UA_Client *client, const void *request,
45978 const UA_DataType *requestType, void *response,
45979 const UA_DataType *responseType) {
45980 /* Initialize. Response is valied in case of aborting. */
45981 UA_init(p: response, type: responseType);
45982
45983 if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) {
45984 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45985 msg: "SecureChannel must be connected before sending requests");
45986 UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
45987 respHeader->serviceResult = UA_STATUSCODE_BADCONNECTIONCLOSED;
45988 return;
45989 }
45990
45991 /* Send the request */
45992 UA_UInt32 requestId;
45993 UA_StatusCode retval = sendSymmetricServiceRequest(client, request, requestType, requestId: &requestId);
45994
45995 UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
45996 if(retval == UA_STATUSCODE_GOOD) {
45997 /* Retrieve the response */
45998 UA_DateTime maxDate = UA_DateTime_nowMonotonic() + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC);
45999 retval = receiveResponse(client, response, responseType, maxDate, synchronousRequestId: &requestId);
46000 } else if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
46001 respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
46002 return;
46003 }
46004
46005 /* In synchronous service, if we have don't have a reply we need to close
46006 * the connection. For all other error cases, receiveResponse has already
46007 * closed the channel. */
46008 if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT ||
46009 client->channel.state == UA_SECURECHANNELSTATE_CLOSING) {
46010 closeSecureChannel(client);
46011 retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
46012 }
46013
46014 if(retval != UA_STATUSCODE_GOOD)
46015 respHeader->serviceResult = retval;
46016
46017 notifyClientState(client);
46018}
46019
46020void
46021UA_Client_AsyncService_cancel(UA_Client *client, AsyncServiceCall *ac,
46022 UA_StatusCode statusCode) {
46023 /* Create an empty response with the statuscode */
46024 UA_Response response;
46025 UA_init(p: &response, type: ac->responseType);
46026 response.responseHeader.serviceResult = statusCode;
46027
46028 if(ac->callback)
46029 ac->callback(client, ac->userdata, ac->requestId, &response);
46030
46031 /* Clean up the response. Users might move data into it. For whatever reasons. */
46032 UA_clear(p: &response, type: ac->responseType);
46033}
46034
46035void UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode) {
46036 AsyncServiceCall *ac, *ac_tmp;
46037 LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) {
46038 LIST_REMOVE(ac, pointers);
46039 UA_Client_AsyncService_cancel(client, ac, statusCode);
46040 UA_free(ptr: ac);
46041 }
46042}
46043
46044UA_StatusCode UA_Client_modifyAsyncCallback(UA_Client *client, UA_UInt32 requestId,
46045 void *userdata, UA_ClientAsyncServiceCallback callback) {
46046 AsyncServiceCall *ac;
46047 LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) {
46048 if(ac->requestId == requestId) {
46049 ac->callback = callback;
46050 ac->userdata = userdata;
46051 return UA_STATUSCODE_GOOD;
46052 }
46053 }
46054
46055 return UA_STATUSCODE_BADNOTFOUND;
46056}
46057
46058UA_StatusCode
46059__UA_Client_AsyncServiceEx(UA_Client *client, const void *request,
46060 const UA_DataType *requestType,
46061 UA_ClientAsyncServiceCallback callback,
46062 const UA_DataType *responseType,
46063 void *userdata, UA_UInt32 *requestId,
46064 UA_UInt32 timeout) {
46065 if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) {
46066 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46067 msg: "SecureChannel must be connected before sending requests");
46068 return UA_STATUSCODE_BADSERVERNOTCONNECTED;
46069 }
46070
46071 /* Prepare the entry for the linked list */
46072 AsyncServiceCall *ac = (AsyncServiceCall*)UA_malloc(size: sizeof(AsyncServiceCall));
46073 if(!ac)
46074 return UA_STATUSCODE_BADOUTOFMEMORY;
46075 ac->callback = callback;
46076 ac->responseType = responseType;
46077 ac->userdata = userdata;
46078 ac->timeout = timeout;
46079
46080 /* Call the service and set the requestId */
46081 UA_StatusCode retval = sendSymmetricServiceRequest(client, request, requestType, requestId: &ac->requestId);
46082 if(retval != UA_STATUSCODE_GOOD) {
46083 UA_free(ptr: ac);
46084 closeSecureChannel(client);
46085 notifyClientState(client);
46086 return retval;
46087 }
46088
46089 ac->start = UA_DateTime_nowMonotonic();
46090
46091 /* Store the entry for async processing */
46092 LIST_INSERT_HEAD(&client->asyncServiceCalls, ac, pointers);
46093 if(requestId)
46094 *requestId = ac->requestId;
46095
46096 notifyClientState(client);
46097 return UA_STATUSCODE_GOOD;
46098}
46099
46100UA_StatusCode
46101__UA_Client_AsyncService(UA_Client *client, const void *request,
46102 const UA_DataType *requestType,
46103 UA_ClientAsyncServiceCallback callback,
46104 const UA_DataType *responseType,
46105 void *userdata, UA_UInt32 *requestId) {
46106 return __UA_Client_AsyncServiceEx(client, request, requestType, callback, responseType,
46107 userdata, requestId, timeout: client->config.timeout);
46108}
46109
46110UA_StatusCode
46111UA_Client_sendAsyncRequest(UA_Client *client, const void *request,
46112 const UA_DataType *requestType,
46113 UA_ClientAsyncServiceCallback callback,
46114 const UA_DataType *responseType, void *userdata,
46115 UA_UInt32 *requestId) {
46116 return __UA_Client_AsyncService(client, request, requestType, callback,
46117 responseType, userdata, requestId);
46118}
46119
46120UA_StatusCode UA_EXPORT
46121UA_Client_addTimedCallback(UA_Client *client, UA_ClientCallback callback,
46122 void *data, UA_DateTime date, UA_UInt64 *callbackId) {
46123 return UA_Timer_addTimedCallback(t: &client->timer, callback: (UA_ApplicationCallback)callback,
46124 application: client, data, date, callbackId);
46125}
46126
46127UA_StatusCode
46128UA_Client_addRepeatedCallback(UA_Client *client, UA_ClientCallback callback,
46129 void *data, UA_Double interval_ms, UA_UInt64 *callbackId) {
46130 return UA_Timer_addRepeatedCallback(t: &client->timer, callback: (UA_ApplicationCallback)callback,
46131 application: client, data, interval_ms, NULL,
46132 timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, callbackId);
46133}
46134
46135UA_StatusCode
46136UA_Client_changeRepeatedCallbackInterval(UA_Client *client, UA_UInt64 callbackId,
46137 UA_Double interval_ms) {
46138 return UA_Timer_changeRepeatedCallback(t: &client->timer, callbackId, interval_ms, NULL, timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
46139}
46140
46141void
46142UA_Client_removeCallback(UA_Client *client, UA_UInt64 callbackId) {
46143 UA_Timer_removeCallback(t: &client->timer, callbackId);
46144}
46145
46146static void
46147asyncServiceTimeoutCheck(UA_Client *client) {
46148 AsyncServiceCall *ac, *ac_tmp;
46149 UA_DateTime now = UA_DateTime_nowMonotonic();
46150 LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) {
46151 if(!ac->timeout)
46152 continue;
46153 if(ac->start + (UA_DateTime)(ac->timeout * UA_DATETIME_MSEC) <= now) {
46154 LIST_REMOVE(ac, pointers);
46155 UA_Client_AsyncService_cancel(client, ac, UA_STATUSCODE_BADTIMEOUT);
46156 UA_free(ptr: ac);
46157 }
46158 }
46159}
46160
46161static void
46162backgroundConnectivityCallback(UA_Client *client, void *userdata,
46163 UA_UInt32 requestId, const UA_ReadResponse *response) {
46164 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) {
46165 if(client->config.inactivityCallback)
46166 client->config.inactivityCallback(client);
46167 }
46168 client->pendingConnectivityCheck = false;
46169 client->lastConnectivityCheck = UA_DateTime_nowMonotonic();
46170}
46171
46172static void
46173UA_Client_backgroundConnectivity(UA_Client *client) {
46174 if(!client->config.connectivityCheckInterval)
46175 return;
46176
46177 if(client->pendingConnectivityCheck)
46178 return;
46179
46180 UA_DateTime now = UA_DateTime_nowMonotonic();
46181 UA_DateTime nextDate = client->lastConnectivityCheck +
46182 (UA_DateTime)(client->config.connectivityCheckInterval * UA_DATETIME_MSEC);
46183 if(now <= nextDate)
46184 return;
46185
46186 /* Prepare the request */
46187 UA_ReadValueId rvid;
46188 UA_ReadValueId_init(p: &rvid);
46189 rvid.attributeId = UA_ATTRIBUTEID_VALUE;
46190 rvid.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STATE);
46191 UA_ReadRequest request;
46192 UA_ReadRequest_init(p: &request);
46193 request.nodesToRead = &rvid;
46194 request.nodesToReadSize = 1;
46195 UA_StatusCode retval =
46196 __UA_Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_READREQUEST],
46197 callback: (UA_ClientAsyncServiceCallback)backgroundConnectivityCallback,
46198 responseType: &UA_TYPES[UA_TYPES_READRESPONSE], NULL, NULL);
46199 if(retval == UA_STATUSCODE_GOOD)
46200 client->pendingConnectivityCheck = true;
46201}
46202
46203static void
46204clientExecuteRepeatedCallback(void *executionApplication, UA_ApplicationCallback cb,
46205 void *callbackApplication, void *data) {
46206 cb(callbackApplication, data);
46207}
46208
46209UA_StatusCode
46210UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) {
46211 /* Process timed (repeated) jobs */
46212 UA_DateTime now = UA_DateTime_nowMonotonic();
46213 UA_DateTime maxDate =
46214 UA_Timer_process(t: &client->timer, nowMonotonic: now, executionCallback: (UA_TimerExecutionCallback)
46215 clientExecuteRepeatedCallback, executionApplication: client);
46216 if(maxDate > now + ((UA_DateTime)timeout * UA_DATETIME_MSEC))
46217 maxDate = now + ((UA_DateTime)timeout * UA_DATETIME_MSEC);
46218
46219 /* Make sure we have an open channel */
46220 UA_StatusCode retval = UA_STATUSCODE_GOOD;
46221 if(client->endpointsHandshake || client->findServersHandshake ||
46222 client->discoveryUrl.length == 0 ||
46223 (client->noSession && client->channel.state != UA_SECURECHANNELSTATE_OPEN) ||
46224 client->sessionState < UA_SESSIONSTATE_ACTIVATED) {
46225 retval = connectIterate(client, timeout);
46226 notifyClientState(client);
46227 return retval;
46228 }
46229
46230 /* Renew Secure Channel */
46231 UA_Client_renewSecureChannel(client);
46232 if(client->connectStatus != UA_STATUSCODE_GOOD)
46233 return client->connectStatus;
46234
46235 /* Feed the server PublishRequests for the Subscriptions */
46236#ifdef UA_ENABLE_SUBSCRIPTIONS
46237 UA_Client_Subscriptions_backgroundPublish(client);
46238#endif
46239
46240 /* Send read requests from time to time to test the connectivity */
46241 UA_Client_backgroundConnectivity(client);
46242
46243 /* Listen on the network for the given timeout */
46244 retval = receiveResponse(client, NULL, NULL, maxDate, NULL);
46245 if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT)
46246 retval = UA_STATUSCODE_GOOD;
46247 if(retval != UA_STATUSCODE_GOOD) {
46248 UA_LOG_WARNING_CHANNEL(&client->config.logger, &client->channel,
46249 "Could not receive with StatusCode %s",
46250 UA_StatusCode_name(retval));
46251 }
46252
46253#ifdef UA_ENABLE_SUBSCRIPTIONS
46254 /* The inactivity check must be done after receiveServiceResponse*/
46255 UA_Client_Subscriptions_backgroundPublishInactivityCheck(client);
46256#endif
46257
46258 /* Did async services time out? Process callbacks with an error code */
46259 asyncServiceTimeoutCheck(client);
46260
46261 /* Log and notify user if the client state has changed */
46262 notifyClientState(client);
46263
46264 return client->connectStatus;
46265}
46266
46267const UA_DataType *
46268UA_Client_findDataType(UA_Client *client, const UA_NodeId *typeId) {
46269 return UA_findDataTypeWithCustom(typeId, customTypes: client->config.customDataTypes);
46270}
46271
46272/**** amalgamated original file "/src/client/ua_client_connect.c" ****/
46273
46274/* This Source Code Form is subject to the terms of the Mozilla Public
46275 * License, v. 2.0. If a copy of the MPL was not distributed with this
46276 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
46277 *
46278 * Copyright 2017-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
46279 * Copyright 2017-2019 (c) Fraunhofer IOSB (Author: Mark Giraud)
46280 */
46281
46282
46283
46284/* Some OPC UA servers only return all Endpoints if the EndpointURL used during
46285 * the HEL/ACK handshake exactly matches -- including the path following the
46286 * address and port! Hence for the first connection we only call FindServers and
46287 * reopen a new TCP connection using then EndpointURL found there.
46288 *
46289 * The overall process is this:
46290 * - Connect with the EndpointURL provided by the user (HEL/ACK)
46291 * - Call FindServers
46292 * - If one of the results has an exactly matching EndpointUrl, continue.
46293 * - Otherwise select a matching server, update the endpointURL member of
46294 * UA_Client and reconnect. -
46295 * - Call GetEndpoints and select an Endpoint
46296 * - Open a SecureChannel and Session for that Endpoint
46297 */
46298
46299#define UA_MINMESSAGESIZE 8192
46300#define UA_SESSION_LOCALNONCELENGTH 32
46301#define MAX_DATA_SIZE 4096
46302
46303static void closeSession(UA_Client *client);
46304static UA_StatusCode createSessionAsync(UA_Client *client);
46305
46306static UA_SecurityPolicy *
46307getSecurityPolicy(UA_Client *client, UA_String policyUri) {
46308 for(size_t i = 0; i < client->config.securityPoliciesSize; i++) {
46309 if(UA_String_equal(s1: &policyUri, s2: &client->config.securityPolicies[i].policyUri))
46310 return &client->config.securityPolicies[i];
46311 }
46312 return NULL;
46313}
46314
46315static UA_Boolean
46316endpointUnconfigured(UA_Client *client) {
46317 char test = 0;
46318 char *pos = (char *)&client->config.endpoint;
46319 for(size_t i = 0; i < sizeof(UA_EndpointDescription); i++)
46320 test = test | *(pos + i);
46321 pos = (char *)&client->config.userTokenPolicy;
46322 for(size_t i = 0; i < sizeof(UA_UserTokenPolicy); i++)
46323 test = test | *(pos + i);
46324 return (test == 0);
46325}
46326
46327#ifdef UA_ENABLE_ENCRYPTION
46328
46329/* Function to create a signature using remote certificate and nonce */
46330static UA_StatusCode
46331signActivateSessionRequest(UA_Client *client, UA_SecureChannel *channel,
46332 UA_ActivateSessionRequest *request) {
46333 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
46334 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
46335 return UA_STATUSCODE_GOOD;
46336
46337 const UA_SecurityPolicy *sp = channel->securityPolicy;
46338 UA_SignatureData *sd = &request->clientSignature;
46339
46340 /* Prepare the signature */
46341 size_t signatureSize = sp->certificateSigningAlgorithm.
46342 getLocalSignatureSize(channel->channelContext);
46343 UA_StatusCode retval = UA_String_copy(src: &sp->certificateSigningAlgorithm.uri,
46344 dst: &sd->algorithm);
46345 if(retval != UA_STATUSCODE_GOOD)
46346 return retval;
46347
46348 retval = UA_ByteString_allocBuffer(bs: &sd->signature, length: signatureSize);
46349 if(retval != UA_STATUSCODE_GOOD)
46350 return retval;
46351
46352 /* Allocate a temporary buffer */
46353 size_t dataToSignSize = channel->remoteCertificate.length + client->remoteNonce.length;
46354 if(dataToSignSize > MAX_DATA_SIZE)
46355 return UA_STATUSCODE_BADINTERNALERROR;
46356
46357 UA_ByteString dataToSign;
46358 retval = UA_ByteString_allocBuffer(bs: &dataToSign, length: dataToSignSize);
46359 if(retval != UA_STATUSCODE_GOOD)
46360 return retval; /* sd->signature is cleaned up with the response */
46361
46362 /* Sign the signature */
46363 memcpy(dest: dataToSign.data, src: channel->remoteCertificate.data,
46364 n: channel->remoteCertificate.length);
46365 memcpy(dest: dataToSign.data + channel->remoteCertificate.length,
46366 src: client->remoteNonce.data, n: client->remoteNonce.length);
46367 retval = sp->certificateSigningAlgorithm.sign(channel->channelContext,
46368 &dataToSign, &sd->signature);
46369
46370 /* Clean up */
46371 UA_ByteString_clear(p: &dataToSign);
46372 return retval;
46373}
46374
46375static UA_StatusCode
46376encryptUserIdentityToken(UA_Client *client, const UA_String *userTokenSecurityPolicy,
46377 UA_ExtensionObject *userIdentityToken) {
46378 UA_IssuedIdentityToken *iit = NULL;
46379 UA_UserNameIdentityToken *unit = NULL;
46380 UA_ByteString *tokenData;
46381 if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]) {
46382 iit = (UA_IssuedIdentityToken*)userIdentityToken->content.decoded.data;
46383 tokenData = &iit->tokenData;
46384 } else if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
46385 unit = (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
46386 tokenData = &unit->password;
46387 } else {
46388 return UA_STATUSCODE_GOOD;
46389 }
46390
46391 /* No encryption */
46392 const UA_String none = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None");
46393 if(userTokenSecurityPolicy->length == 0 ||
46394 UA_String_equal(s1: userTokenSecurityPolicy, s2: &none)) {
46395 return UA_STATUSCODE_GOOD;
46396 }
46397
46398 UA_SecurityPolicy *sp = getSecurityPolicy(client, policyUri: *userTokenSecurityPolicy);
46399 if(!sp) {
46400 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK,
46401 msg: "Could not find the required SecurityPolicy for the UserToken");
46402 return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
46403 }
46404
46405 /* Create a temp channel context */
46406
46407 void *channelContext;
46408 UA_StatusCode retval = sp->channelModule.
46409 newContext(sp, &client->config.endpoint.serverCertificate, &channelContext);
46410 if(retval != UA_STATUSCODE_GOOD) {
46411 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK,
46412 msg: "Could not instantiate the SecurityPolicy for the UserToken");
46413 return UA_STATUSCODE_BADINTERNALERROR;
46414 }
46415
46416 /* Compute the encrypted length (at least one byte padding) */
46417 size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
46418 encryptionAlgorithm.getRemotePlainTextBlockSize(channelContext);
46419 size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
46420 encryptionAlgorithm.getRemoteBlockSize(channelContext);
46421 UA_UInt32 length = (UA_UInt32)(tokenData->length + client->remoteNonce.length);
46422 UA_UInt32 totalLength = length + 4; /* Including the length field */
46423 size_t blocks = totalLength / plainTextBlockSize;
46424 if(totalLength % plainTextBlockSize != 0)
46425 blocks++;
46426 size_t encryptedLength = blocks * encryptedBlockSize;
46427
46428 /* Allocate memory for encryption overhead */
46429 UA_ByteString encrypted;
46430 retval = UA_ByteString_allocBuffer(bs: &encrypted, length: encryptedLength);
46431 if(retval != UA_STATUSCODE_GOOD) {
46432 sp->channelModule.deleteContext(channelContext);
46433 return UA_STATUSCODE_BADOUTOFMEMORY;
46434 }
46435
46436 UA_Byte *pos = encrypted.data;
46437 const UA_Byte *end = &encrypted.data[encrypted.length];
46438 retval = UA_UInt32_encodeBinary(src: &length, bufPos: &pos, bufEnd: end);
46439 memcpy(dest: pos, src: tokenData->data, n: tokenData->length);
46440 memcpy(dest: &pos[tokenData->length], src: client->remoteNonce.data, n: client->remoteNonce.length);
46441 UA_assert(retval == UA_STATUSCODE_GOOD);
46442
46443 /* Add padding
46444 *
46445 * 7.36.2.2 Legacy Encrypted Token Secret Format: A Client should not add any
46446 * padding after the secret. If a Client adds padding then all bytes shall
46447 * be zero. A Server shall check for padding added by Clients and ensure
46448 * that all padding bytes are zeros. */
46449 size_t paddedLength = plainTextBlockSize * blocks;
46450 for(size_t i = totalLength; i < paddedLength; i++)
46451 encrypted.data[i] = 0;
46452 encrypted.length = paddedLength;
46453
46454 retval = sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
46455 encrypt(channelContext, &encrypted);
46456 encrypted.length = encryptedLength;
46457
46458 if(iit) {
46459 retval |= UA_String_copy(src: &sp->asymmetricModule.cryptoModule.encryptionAlgorithm.uri,
46460 dst: &iit->encryptionAlgorithm);
46461 } else {
46462 retval |= UA_String_copy(src: &sp->asymmetricModule.cryptoModule.encryptionAlgorithm.uri,
46463 dst: &unit->encryptionAlgorithm);
46464 }
46465
46466 UA_ByteString_clear(p: tokenData);
46467 *tokenData = encrypted;
46468
46469 /* Delete the temp channel context */
46470 sp->channelModule.deleteContext(channelContext);
46471
46472 return retval;
46473}
46474
46475/* Function to verify the signature corresponds to ClientNonce
46476 * using the local certificate */
46477static UA_StatusCode
46478checkCreateSessionSignature(UA_Client *client, const UA_SecureChannel *channel,
46479 const UA_CreateSessionResponse *response) {
46480 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
46481 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
46482 return UA_STATUSCODE_GOOD;
46483
46484 if(!channel->securityPolicy)
46485 return UA_STATUSCODE_BADINTERNALERROR;
46486
46487 const UA_SecurityPolicy *sp = channel->securityPolicy;
46488 const UA_ByteString *lc = &sp->localCertificate;
46489
46490 size_t dataToVerifySize = lc->length + client->localNonce.length;
46491 UA_ByteString dataToVerify = UA_BYTESTRING_NULL;
46492 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &dataToVerify, length: dataToVerifySize);
46493 if(retval != UA_STATUSCODE_GOOD)
46494 return retval;
46495
46496 memcpy(dest: dataToVerify.data, src: lc->data, n: lc->length);
46497 memcpy(dest: dataToVerify.data + lc->length,
46498 src: client->localNonce.data, n: client->localNonce.length);
46499
46500 retval = sp->certificateSigningAlgorithm.verify(channel->channelContext, &dataToVerify,
46501 &response->serverSignature.signature);
46502 UA_ByteString_clear(p: &dataToVerify);
46503 return retval;
46504}
46505
46506#endif
46507
46508/***********************/
46509/* Open the Connection */
46510/***********************/
46511
46512void
46513processERRResponse(UA_Client *client, const UA_ByteString *chunk) {
46514 client->channel.state = UA_SECURECHANNELSTATE_CLOSING;
46515
46516 size_t offset = 0;
46517 UA_TcpErrorMessage errMessage;
46518 UA_StatusCode res =
46519 UA_decodeBinaryInternal(src: chunk, offset: &offset, dst: &errMessage,
46520 type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE], NULL);
46521 if(res != UA_STATUSCODE_GOOD) {
46522 UA_LOG_ERROR_CHANNEL(&client->config.logger, &client->channel,
46523 "Received an ERR response that could not be decoded with StatusCode %s",
46524 UA_StatusCode_name(res));
46525 client->connectStatus = res;
46526 return;
46527 }
46528
46529 UA_LOG_ERROR_CHANNEL(&client->config.logger, &client->channel,
46530 "Received an ERR response with StatusCode %s and the following reason: %.*s",
46531 UA_StatusCode_name(errMessage.error), (int)errMessage.reason.length, errMessage.reason.data);
46532 client->connectStatus = errMessage.error;
46533 UA_TcpErrorMessage_clear(p: &errMessage);
46534}
46535
46536void
46537processACKResponse(UA_Client *client, const UA_ByteString *chunk) {
46538 UA_SecureChannel *channel = &client->channel;
46539 if(channel->state != UA_SECURECHANNELSTATE_HEL_SENT) {
46540 UA_LOG_ERROR_CHANNEL(&client->config.logger, channel,
46541 "Expected an ACK response");
46542 channel->state = UA_SECURECHANNELSTATE_CLOSING;
46543 return;
46544 }
46545
46546 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK, msg: "Received ACK message");
46547
46548 /* Decode the message */
46549 size_t offset = 0;
46550 UA_TcpAcknowledgeMessage ackMessage;
46551 client->connectStatus =
46552 UA_decodeBinaryInternal(src: chunk, offset: &offset, dst: &ackMessage,
46553 type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE], NULL);
46554 if(client->connectStatus != UA_STATUSCODE_GOOD) {
46555 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK,
46556 msg: "Decoding ACK message failed");
46557 closeSecureChannel(client);
46558 return;
46559 }
46560
46561 client->connectStatus =
46562 UA_SecureChannel_processHELACK(channel, remoteConfig: &ackMessage);
46563 if(client->connectStatus != UA_STATUSCODE_GOOD) {
46564 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK,
46565 msg: "Processing the ACK message failed with StatusCode %s",
46566 UA_StatusCode_name(code: client->connectStatus));
46567 closeSecureChannel(client);
46568 return;
46569 }
46570
46571 client->channel.state = UA_SECURECHANNELSTATE_ACK_RECEIVED;
46572}
46573
46574static UA_StatusCode
46575sendHELMessage(UA_Client *client) {
46576 /* Get a buffer */
46577 UA_ByteString message;
46578 UA_Connection *conn = &client->connection;
46579 UA_StatusCode retval = conn->getSendBuffer(conn, UA_MINMESSAGESIZE, &message);
46580 if(retval != UA_STATUSCODE_GOOD)
46581 return retval;
46582
46583 /* Prepare the HEL message and encode at offset 8 */
46584 UA_TcpHelloMessage hello;
46585 hello.protocolVersion = 0;
46586 hello.receiveBufferSize = client->config.localConnectionConfig.recvBufferSize;
46587 hello.sendBufferSize = client->config.localConnectionConfig.sendBufferSize;
46588 hello.maxMessageSize = client->config.localConnectionConfig.localMaxMessageSize;
46589 hello.maxChunkCount = client->config.localConnectionConfig.localMaxChunkCount;
46590
46591 /* Use the DiscoveryUrl -- if already known via FindServers */
46592 if(client->discoveryUrl.length > 0) {
46593 hello.endpointUrl = client->discoveryUrl;
46594 } else {
46595 hello.endpointUrl = client->endpointUrl;
46596 }
46597
46598 UA_Byte *bufPos = &message.data[8]; /* skip the header */
46599 const UA_Byte *bufEnd = &message.data[message.length];
46600 client->connectStatus =
46601 UA_encodeBinaryInternal(src: &hello, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE],
46602 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
46603
46604 /* Encode the message header at offset 0 */
46605 UA_TcpMessageHeader messageHeader;
46606 messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL;
46607 messageHeader.messageSize = (UA_UInt32) ((uintptr_t)bufPos - (uintptr_t)message.data);
46608 bufPos = message.data;
46609 retval = UA_encodeBinaryInternal(src: &messageHeader,
46610 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
46611 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
46612 if(retval != UA_STATUSCODE_GOOD) {
46613 conn->releaseSendBuffer(conn, &message);
46614 return retval;
46615 }
46616
46617 /* Send the HEL message */
46618 message.length = messageHeader.messageSize;
46619 retval = conn->send(conn, &message);
46620 if(retval == UA_STATUSCODE_GOOD) {
46621 client->channel.state = UA_SECURECHANNELSTATE_HEL_SENT;
46622 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK, msg: "Sent HEL message");
46623 } else {
46624 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK, msg: "Sending HEL failed");
46625 }
46626 return retval;
46627}
46628
46629void
46630processOPNResponse(UA_Client *client, const UA_ByteString *message) {
46631 /* Is the content of the expected type? */
46632 size_t offset = 0;
46633 UA_NodeId responseId;
46634 UA_NodeId expectedId =
46635 UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_OPENSECURECHANNELRESPONSE_ENCODING_DEFAULTBINARY);
46636 UA_StatusCode retval = UA_NodeId_decodeBinary(src: message, offset: &offset, dst: &responseId);
46637 if(retval != UA_STATUSCODE_GOOD) {
46638 closeSecureChannel(client);
46639 return;
46640 }
46641
46642 if(!UA_NodeId_equal(n1: &responseId, n2: &expectedId)) {
46643 UA_NodeId_clear(p: &responseId);
46644 closeSecureChannel(client);
46645 return;
46646 }
46647
46648 /* Decode the response */
46649 UA_OpenSecureChannelResponse response;
46650 retval = UA_decodeBinaryInternal(src: message, offset: &offset, dst: &response,
46651 type: &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE], NULL);
46652 if(retval != UA_STATUSCODE_GOOD) {
46653 closeSecureChannel(client);
46654 return;
46655 }
46656
46657 /* Check whether the nonce was reused */
46658 if(client->channel.securityMode != UA_MESSAGESECURITYMODE_NONE &&
46659 UA_ByteString_equal(string1: &client->channel.remoteNonce,
46660 string2: &response.serverNonce)) {
46661 UA_LOG_ERROR_CHANNEL(&client->config.logger, &client->channel,
46662 "The server reused the last nonce");
46663 client->connectStatus = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
46664 closeSecureChannel(client);
46665 return;
46666 }
46667
46668 /* Response.securityToken.revisedLifetime is UInt32 we need to cast it to
46669 * DateTime=Int64 we take 75% of lifetime to start renewing as described in
46670 * standard */
46671 client->nextChannelRenewal = UA_DateTime_nowMonotonic()
46672 + (UA_DateTime) (response.securityToken.revisedLifetime
46673 * (UA_Double) UA_DATETIME_MSEC * 0.75);
46674
46675 /* Move the nonce out of the response */
46676 UA_ByteString_clear(p: &client->channel.remoteNonce);
46677 client->channel.remoteNonce = response.serverNonce;
46678 UA_ByteString_init(p: &response.serverNonce);
46679 UA_ResponseHeader_clear(p: &response.responseHeader);
46680
46681 /* Replace the token. Keep the current token as the old token. Messages
46682 * might still arrive for the old token. */
46683 client->channel.altSecurityToken = client->channel.securityToken;
46684 client->channel.securityToken = response.securityToken;
46685 client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT;
46686
46687 /* Compute the new local keys. The remote keys are updated when a message
46688 * with the new SecurityToken is received. */
46689 retval = UA_SecureChannel_generateLocalKeys(channel: &client->channel);
46690 if(retval != UA_STATUSCODE_GOOD) {
46691 closeSecureChannel(client);
46692 return;
46693 }
46694
46695 UA_Float lifetime = (UA_Float)response.securityToken.revisedLifetime / 1000;
46696 UA_Boolean renew = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
46697 if(renew) {
46698 UA_LOG_INFO_CHANNEL(&client->config.logger, &client->channel, "SecureChannel "
46699 "renewed with a revised lifetime of %.2fs", lifetime);
46700 } else {
46701 UA_LOG_INFO_CHANNEL(&client->config.logger, &client->channel,
46702 "SecureChannel opened with SecurityPolicy %.*s "
46703 "and a revised lifetime of %.2fs",
46704 (int)client->channel.securityPolicy->policyUri.length,
46705 client->channel.securityPolicy->policyUri.data, lifetime);
46706 }
46707
46708 client->channel.state = UA_SECURECHANNELSTATE_OPEN;
46709}
46710
46711/* OPN messges to renew the channel are sent asynchronous */
46712static UA_StatusCode
46713sendOPNAsync(UA_Client *client, UA_Boolean renew) {
46714 UA_Connection *conn = &client->connection;
46715 if(conn->state != UA_CONNECTIONSTATE_ESTABLISHED) {
46716 closeSecureChannel(client);
46717 return UA_STATUSCODE_BADNOTCONNECTED;
46718 }
46719
46720 UA_StatusCode retval = UA_SecureChannel_generateLocalNonce(channel: &client->channel);
46721 if(retval != UA_STATUSCODE_GOOD)
46722 return retval;
46723
46724 /* Prepare the OpenSecureChannelRequest */
46725 UA_OpenSecureChannelRequest opnSecRq;
46726 UA_OpenSecureChannelRequest_init(p: &opnSecRq);
46727 opnSecRq.requestHeader.timestamp = UA_DateTime_now();
46728 opnSecRq.requestHeader.authenticationToken = client->authenticationToken;
46729 opnSecRq.securityMode = client->channel.securityMode;
46730 opnSecRq.clientNonce = client->channel.localNonce;
46731 opnSecRq.requestedLifetime = client->config.secureChannelLifeTime;
46732 if(renew) {
46733 opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW;
46734 UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
46735 "Requesting to renew the SecureChannel");
46736 } else {
46737 opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
46738 UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
46739 "Requesting to open a SecureChannel");
46740 }
46741
46742 /* Prepare the entry for the linked list */
46743 UA_UInt32 requestId = ++client->requestId;
46744
46745 /* Send the OPN message */
46746 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_SECURECHANNEL,
46747 msg: "Requesting to open a SecureChannel");
46748 retval =
46749 UA_SecureChannel_sendAsymmetricOPNMessage(channel: &client->channel, requestId, content: &opnSecRq,
46750 contentType: &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST]);
46751 if(retval != UA_STATUSCODE_GOOD) {
46752 client->connectStatus = retval;
46753 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_SECURECHANNEL,
46754 msg: "Sending OPN message failed with error %s",
46755 UA_StatusCode_name(code: retval));
46756 closeSecureChannel(client);
46757 return retval;
46758 }
46759
46760 client->channel.renewState = UA_SECURECHANNELRENEWSTATE_SENT;
46761 if(client->channel.state < UA_SECURECHANNELSTATE_OPN_SENT)
46762 client->channel.state = UA_SECURECHANNELSTATE_OPN_SENT;
46763 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_SECURECHANNEL, msg: "OPN message sent");
46764 return UA_STATUSCODE_GOOD;
46765}
46766
46767UA_StatusCode
46768UA_Client_renewSecureChannel(UA_Client *client) {
46769 /* Check if OPN has been sent or the SecureChannel is still valid */
46770 if(client->channel.state != UA_SECURECHANNELSTATE_OPEN ||
46771 client->channel.renewState == UA_SECURECHANNELRENEWSTATE_SENT ||
46772 client->nextChannelRenewal > UA_DateTime_nowMonotonic())
46773 return UA_STATUSCODE_GOODCALLAGAIN;
46774 sendOPNAsync(client, true);
46775 return client->connectStatus;
46776}
46777
46778static void
46779responseActivateSession(UA_Client *client, void *userdata, UA_UInt32 requestId,
46780 void *response) {
46781 UA_ActivateSessionResponse *activateResponse =
46782 (UA_ActivateSessionResponse *)response;
46783 if(activateResponse->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
46784 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46785 msg: "ActivateSession failed with error code %s",
46786 UA_StatusCode_name(code: activateResponse->responseHeader.serviceResult));
46787 if(activateResponse->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONIDINVALID ||
46788 activateResponse->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONCLOSED) {
46789 /* The session is lost. Create a new one. */
46790 closeSession(client);
46791 createSessionAsync(client);
46792 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46793 msg: "Session cannot be activated. Create a new Session.");
46794 } else {
46795 /* Something else is wrong. Give up. */
46796 client->connectStatus = activateResponse->responseHeader.serviceResult;
46797 }
46798 return;
46799 }
46800
46801 /* Replace the nonce */
46802 UA_ByteString_clear(p: &client->remoteNonce);
46803 client->remoteNonce = activateResponse->serverNonce;
46804 UA_ByteString_init(p: &activateResponse->serverNonce);
46805
46806 client->sessionState = UA_SESSIONSTATE_ACTIVATED;
46807 notifyClientState(client);
46808}
46809
46810static UA_StatusCode
46811activateSessionAsync(UA_Client *client) {
46812 UA_ActivateSessionRequest request;
46813 UA_ActivateSessionRequest_init(p: &request);
46814 request.requestHeader.requestHandle = ++client->requestHandle;
46815 request.requestHeader.timestamp = UA_DateTime_now ();
46816 request.requestHeader.timeoutHint = 600000;
46817 UA_StatusCode retval =
46818 UA_ExtensionObject_copy(src: &client->config.userIdentityToken, dst: &request.userIdentityToken);
46819 if(retval != UA_STATUSCODE_GOOD)
46820 return retval;
46821
46822 if (client->config.sessionLocaleIdsSize && client->config.sessionLocaleIds) {
46823 retval = UA_Array_copy(src: client->config.sessionLocaleIds, size: client->config.sessionLocaleIdsSize,
46824 dst: (void **)&request.localeIds, type: &UA_TYPES[UA_TYPES_LOCALEID]);
46825 if (retval != UA_STATUSCODE_GOOD)
46826 return retval;
46827
46828 request.localeIdsSize = client->config.sessionLocaleIdsSize;
46829 }
46830
46831 /* If not token is set, use anonymous */
46832 if(request.userIdentityToken.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
46833 UA_AnonymousIdentityToken *t = UA_AnonymousIdentityToken_new();
46834 if(!t) {
46835 UA_ActivateSessionRequest_clear(p: &request);
46836 return UA_STATUSCODE_BADOUTOFMEMORY;
46837 }
46838 request.userIdentityToken.content.decoded.data = t;
46839 request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN];
46840 request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
46841 }
46842
46843 /* Set the policy-Id from the endpoint. Every IdentityToken starts with a
46844 * string. */
46845 retval = UA_String_copy(src: &client->config.userTokenPolicy.policyId,
46846 dst: (UA_String*)request.userIdentityToken.content.decoded.data);
46847
46848#ifdef UA_ENABLE_ENCRYPTION
46849 /* Encrypt the UserIdentityToken */
46850 const UA_String *userTokenPolicy = &client->channel.securityPolicy->policyUri;
46851 if(client->config.userTokenPolicy.securityPolicyUri.length > 0)
46852 userTokenPolicy = &client->config.userTokenPolicy.securityPolicyUri;
46853 retval |= encryptUserIdentityToken(client, userTokenSecurityPolicy: userTokenPolicy, userIdentityToken: &request.userIdentityToken);
46854 retval |= signActivateSessionRequest(client, channel: &client->channel, request: &request);
46855#endif
46856
46857 if(retval == UA_STATUSCODE_GOOD)
46858 retval = UA_Client_sendAsyncRequest(client, request: &request,
46859 requestType: &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
46860 callback: (UA_ClientAsyncServiceCallback) responseActivateSession,
46861 responseType: &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE], NULL, NULL);
46862
46863 UA_ActivateSessionRequest_clear(p: &request);
46864 if(retval == UA_STATUSCODE_GOOD)
46865 client->sessionState = UA_SESSIONSTATE_ACTIVATE_REQUESTED;
46866 else
46867 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46868 msg: "ActivateSession failed when sending the request with error code %s",
46869 UA_StatusCode_name(code: retval));
46870
46871 return retval;
46872}
46873
46874/* Combination of UA_Client_getEndpointsInternal and getEndpoints */
46875static void
46876responseGetEndpoints(UA_Client *client, void *userdata, UA_UInt32 requestId,
46877 void *response) {
46878 client->endpointsHandshake = false;
46879
46880 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46881 msg: "Received FindServersResponse");
46882
46883 UA_GetEndpointsResponse *resp = (UA_GetEndpointsResponse*)response;
46884 /* GetEndpoints not possible. Fail the connection */
46885 if(resp->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
46886 client->connectStatus = resp->responseHeader.serviceResult;
46887 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46888 msg: "GetEndpointRequest failed with error code %s",
46889 UA_StatusCode_name(code: client->connectStatus));
46890 UA_GetEndpointsResponse_clear(p: resp);
46891 return;
46892 }
46893
46894 /* Warn if the Endpoints look incomplete / don't match the EndpointUrl */
46895 Client_warnEndpointsResult(client, response: resp, endpointUrl: &client->discoveryUrl);
46896
46897 UA_Boolean endpointFound = false;
46898 UA_Boolean tokenFound = false;
46899 const UA_String binaryTransport = UA_STRING(chars: "http://opcfoundation.org/UA-Profile/"
46900 "Transport/uatcp-uasc-uabinary");
46901
46902 /* Find a matching combination of Endpoint and UserTokenPolicy */
46903 for(size_t i = 0; i < resp->endpointsSize; ++i) {
46904 UA_EndpointDescription* endpoint = &resp->endpoints[i];
46905
46906 /* Filter by the ApplicationURI if defined */
46907 if(client->config.applicationUri.length > 0 &&
46908 !UA_String_equal(s1: &client->config.applicationUri,
46909 s2: &endpoint->server.applicationUri))
46910 continue;
46911
46912 /* Look out for binary transport endpoints.
46913 * Note: Siemens returns empty ProfileUrl, we will accept it as binary. */
46914 if(endpoint->transportProfileUri.length != 0 &&
46915 !UA_String_equal (s1: &endpoint->transportProfileUri, s2: &binaryTransport))
46916 continue;
46917
46918 /* Valid SecurityMode? */
46919 if(endpoint->securityMode < 1 || endpoint->securityMode > 3) {
46920 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46921 msg: "Rejecting endpoint %lu: invalid security mode",
46922 (long unsigned)i);
46923 continue;
46924 }
46925
46926 /* Selected SecurityMode? */
46927 if(client->config.securityMode > 0 &&
46928 client->config.securityMode != endpoint->securityMode) {
46929 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46930 msg: "Rejecting endpoint %lu: security mode doesn't match",
46931 (long unsigned)i);
46932 continue;
46933 }
46934
46935 /* Matching SecurityPolicy? */
46936 if(client->config.securityPolicyUri.length > 0 &&
46937 !UA_String_equal(s1: &client->config.securityPolicyUri,
46938 s2: &endpoint->securityPolicyUri)) {
46939 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46940 msg: "Rejecting endpoint %lu: security policy doesn't match",
46941 (long unsigned)i);
46942 continue;
46943 }
46944
46945 /* SecurityPolicy available? */
46946 if(!getSecurityPolicy(client, policyUri: endpoint->securityPolicyUri)) {
46947 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46948 msg: "Rejecting endpoint %lu: security policy not available",
46949 (long unsigned)i);
46950 continue;
46951 }
46952
46953 endpointFound = true;
46954
46955 /* Look for a user token policy with an anonymous token */
46956 for(size_t j = 0; j < endpoint->userIdentityTokensSize; ++j) {
46957 UA_UserTokenPolicy* tokenPolicy = &endpoint->userIdentityTokens[j];
46958 const UA_DataType *tokenType = client->config.userIdentityToken.content.decoded.type;
46959
46960 /* Usertokens also have a security policy... */
46961 if(tokenPolicy->tokenType != UA_USERTOKENTYPE_ANONYMOUS &&
46962 tokenPolicy->securityPolicyUri.length > 0 &&
46963 !getSecurityPolicy(client, policyUri: tokenPolicy->securityPolicyUri)) {
46964 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46965 msg: "Rejecting UserTokenPolicy %lu in endpoint %lu: "
46966 "security policy '%.*s' not available", (long unsigned)j, (long unsigned)i,
46967 (int)tokenPolicy->securityPolicyUri.length,
46968 tokenPolicy->securityPolicyUri.data);
46969 continue;
46970 }
46971
46972 if(tokenPolicy->tokenType > 3) {
46973 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46974 msg: "Rejecting UserTokenPolicy %lu in endpoint %lu: invalid token type",
46975 (long unsigned)j, (long unsigned)i);
46976 continue;
46977 }
46978
46979 if(tokenPolicy->tokenType == UA_USERTOKENTYPE_ANONYMOUS &&
46980 tokenType != &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN] &&
46981 tokenType != NULL) {
46982 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46983 msg: "Rejecting UserTokenPolicy %lu (anonymous) in endpoint %lu: "
46984 "configuration doesn't match", (long unsigned)j, (long unsigned)i);
46985 continue;
46986 }
46987 if(tokenPolicy->tokenType == UA_USERTOKENTYPE_USERNAME &&
46988 tokenType != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
46989 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46990 msg: "Rejecting UserTokenPolicy %lu (username) in endpoint %lu: "
46991 "configuration doesn't match", (long unsigned)j, (long unsigned)i);
46992 continue;
46993 }
46994 if(tokenPolicy->tokenType == UA_USERTOKENTYPE_CERTIFICATE &&
46995 tokenType != &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
46996 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46997 msg: "Rejecting UserTokenPolicy %lu (certificate) in endpoint %lu: "
46998 "configuration doesn't match", (long unsigned)j, (long unsigned)i);
46999 continue;
47000 }
47001 if(tokenPolicy->tokenType == UA_USERTOKENTYPE_ISSUEDTOKEN &&
47002 tokenType != &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]) {
47003 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47004 msg: "Rejecting UserTokenPolicy %lu (token) in endpoint %lu: "
47005 "configuration doesn't match", (long unsigned)j, (long unsigned)i);
47006 continue;
47007 }
47008
47009 /* Endpoint with matching usertokenpolicy found */
47010
47011#if UA_LOGLEVEL <= 300
47012 const char *securityModeNames[3] = {"None", "Sign", "SignAndEncrypt"};
47013 const char *userTokenTypeNames[4] = {"Anonymous", "UserName",
47014 "Certificate", "IssuedToken"};
47015 UA_String *securityPolicyUri = &tokenPolicy->securityPolicyUri;
47016 if(securityPolicyUri->length == 0)
47017 securityPolicyUri = &endpoint->securityPolicyUri;
47018
47019 /* Log the selected endpoint */
47020 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47021 msg: "Selected endpoint %lu in URL %.*s with SecurityMode %s and SecurityPolicy %.*s",
47022 (long unsigned)i, (int)endpoint->endpointUrl.length,
47023 endpoint->endpointUrl.data,
47024 securityModeNames[endpoint->securityMode - 1],
47025 (int)endpoint->securityPolicyUri.length,
47026 endpoint->securityPolicyUri.data);
47027
47028 /* Log the selected UserTokenPolicy */
47029 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47030 msg: "Selected UserTokenPolicy %.*s with UserTokenType %s and SecurityPolicy %.*s",
47031 (int)tokenPolicy->policyId.length, tokenPolicy->policyId.data,
47032 userTokenTypeNames[tokenPolicy->tokenType],
47033 (int)securityPolicyUri->length, securityPolicyUri->data);
47034#endif
47035
47036 /* Move to the client config */
47037 tokenFound = true;
47038 UA_EndpointDescription_clear(p: &client->config.endpoint);
47039 client->config.endpoint = *endpoint;
47040 UA_EndpointDescription_init(p: endpoint);
47041 UA_UserTokenPolicy_clear(p: &client->config.userTokenPolicy);
47042 client->config.userTokenPolicy = *tokenPolicy;
47043 UA_UserTokenPolicy_init(p: tokenPolicy);
47044
47045 break;
47046 }
47047
47048 if(tokenFound)
47049 break;
47050 }
47051
47052 if(!endpointFound) {
47053 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47054 msg: "No suitable endpoint found");
47055 client->connectStatus = UA_STATUSCODE_BADINTERNALERROR;
47056 } else if(!tokenFound) {
47057 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47058 msg: "No suitable UserTokenPolicy found for the possible endpoints");
47059 client->connectStatus = UA_STATUSCODE_BADINTERNALERROR;
47060 }
47061
47062 /* Close the SecureChannel if a different SecurityPolicy is defined by the Endpoint */
47063 if(client->config.endpoint.securityMode != client->channel.securityMode ||
47064 !UA_String_equal(s1: &client->config.endpoint.securityPolicyUri,
47065 s2: &client->channel.securityPolicy->policyUri))
47066 closeSecureChannel(client);
47067}
47068
47069static UA_StatusCode
47070requestGetEndpoints(UA_Client *client) {
47071 UA_GetEndpointsRequest request;
47072 UA_GetEndpointsRequest_init(p: &request);
47073 request.requestHeader.timestamp = UA_DateTime_now();
47074 request.requestHeader.timeoutHint = 10000;
47075 if(client->discoveryUrl.length > 0)
47076 request.endpointUrl = client->discoveryUrl;
47077 else
47078 request.endpointUrl = client->endpointUrl;
47079 UA_StatusCode retval =
47080 UA_Client_sendAsyncRequest(client, request: &request, requestType: &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
47081 callback: (UA_ClientAsyncServiceCallback) responseGetEndpoints,
47082 responseType: &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE], NULL, NULL);
47083 if(retval == UA_STATUSCODE_GOOD)
47084 client->endpointsHandshake = true;
47085 else
47086 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47087 msg: "RequestGetEndpoints failed when sending the request with error code %s",
47088 UA_StatusCode_name(code: retval));
47089 return retval;
47090}
47091
47092static void
47093responseFindServers(UA_Client *client, void *userdata,
47094 UA_UInt32 requestId, void *response) {
47095 client->findServersHandshake = false;
47096
47097 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47098 msg: "Received FindServersResponse");
47099
47100 /* Error handling. Log the error but continue to connect with the current
47101 * EndpointURL. */
47102 UA_FindServersResponse *fsr = (UA_FindServersResponse*)response;
47103 if(fsr->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
47104 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47105 msg: "FindServers failed with error code %s. Continue with the "
47106 "EndpointURL %.*s.",
47107 UA_StatusCode_name(code: fsr->responseHeader.serviceResult),
47108 (int)client->endpointUrl.length, client->endpointUrl.data);
47109 UA_String_copy(src: &client->endpointUrl, dst: &client->discoveryUrl);
47110 return;
47111 }
47112
47113 /* Check if one of the returned servers matches the EndpointURL already used */
47114 for(size_t i = 0; i < fsr->serversSize; i++) {
47115 UA_ApplicationDescription *server = &fsr->servers[i];
47116
47117 /* Filter by the ApplicationURI if defined */
47118 if(client->config.applicationUri.length > 0 &&
47119 !UA_String_equal(s1: &client->config.applicationUri,
47120 s2: &server->applicationUri))
47121 continue;
47122
47123 for(size_t j = 0; j < server->discoveryUrlsSize; j++) {
47124 if(UA_String_equal(s1: &client->endpointUrl, s2: &server->discoveryUrls[j])) {
47125 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47126 msg: "The initially defined EndpointURL %.*s"
47127 "is valid for the server",
47128 (int)client->endpointUrl.length,
47129 client->endpointUrl.data);
47130 UA_String_copy(src: &client->endpointUrl, dst: &client->discoveryUrl);
47131 return;
47132 }
47133 }
47134 }
47135
47136 /* The current EndpointURL is not usable. Pick the first DiscoveryUrl of a
47137 * returned server. */
47138 for(size_t i = 0; i < fsr->serversSize; i++) {
47139 UA_ApplicationDescription *server = &fsr->servers[i];
47140 if(server->applicationType != UA_APPLICATIONTYPE_SERVER)
47141 continue;
47142 if(server->discoveryUrlsSize == 0)
47143 continue;
47144
47145 /* Filter by the ApplicationURI if defined */
47146 if(client->config.applicationUri.length > 0 &&
47147 !UA_String_equal(s1: &client->config.applicationUri,
47148 s2: &server->applicationUri))
47149 continue;
47150
47151 /* Use this DiscoveryUrl in the client */
47152 UA_String_clear(p: &client->discoveryUrl);
47153 client->discoveryUrl = server->discoveryUrls[0];
47154 UA_String_init(p: &server->discoveryUrls[0]);
47155
47156 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47157 msg: "Use the EndpointURL %.*s returned from FindServers",
47158 (int)client->discoveryUrl.length,
47159 client->discoveryUrl.data);
47160
47161 /* Close the SecureChannel to build it up new with the correct
47162 * EndpointURL in the HEL/ACK handshake */
47163 closeSecureChannel(client);
47164 return;
47165 }
47166
47167 /* Could not find a suitable server. Try to continue. */
47168 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47169 msg: "FindServers did not returned a suitable DiscoveryURL. "
47170 "Continue with the EndpointURL %.*s.",
47171 (int)client->endpointUrl.length, client->endpointUrl.data);
47172 UA_String_copy(src: &client->endpointUrl, dst: &client->discoveryUrl);
47173}
47174
47175static UA_StatusCode
47176requestFindServers(UA_Client *client) {
47177 UA_FindServersRequest request;
47178 UA_FindServersRequest_init(p: &request);
47179 request.requestHeader.timestamp = UA_DateTime_now();
47180 request.requestHeader.timeoutHint = 10000;
47181 request.endpointUrl = client->endpointUrl;
47182 UA_StatusCode retval =
47183 UA_Client_sendAsyncRequest(client, request: &request, requestType: &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST],
47184 callback: (UA_ClientAsyncServiceCallback) responseFindServers,
47185 responseType: &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE], NULL, NULL);
47186 if(retval != UA_STATUSCODE_GOOD) {
47187 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47188 msg: "FindServers failed when sending the request with error code %s",
47189 UA_StatusCode_name(code: retval));
47190 return retval;
47191 }
47192
47193 client->findServersHandshake = true;
47194 return UA_STATUSCODE_GOOD;
47195}
47196
47197static void
47198responseSessionCallback(UA_Client *client, void *userdata,
47199 UA_UInt32 requestId, void *response) {
47200 UA_CreateSessionResponse *sessionResponse = (UA_CreateSessionResponse*)response;
47201 UA_StatusCode res = sessionResponse->responseHeader.serviceResult;
47202 if(res != UA_STATUSCODE_GOOD)
47203 goto cleanup;
47204
47205#ifdef UA_ENABLE_ENCRYPTION
47206 if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
47207 client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
47208 /* Verify the session response was created with the same certificate as
47209 * the SecureChannel */
47210 if(!UA_ByteString_equal(string1: &sessionResponse->serverCertificate,
47211 string2: &client->channel.remoteCertificate)) {
47212 res = UA_STATUSCODE_BADCERTIFICATEINVALID;
47213 goto cleanup;
47214 }
47215
47216 /* Verify the client signature */
47217 res = checkCreateSessionSignature(client, channel: &client->channel, response: sessionResponse);
47218 if(res != UA_STATUSCODE_GOOD)
47219 goto cleanup;
47220 }
47221#endif
47222
47223 /* Copy nonce and AuthenticationToken */
47224 UA_ByteString_clear(p: &client->remoteNonce);
47225 UA_NodeId_clear(p: &client->authenticationToken);
47226 res |= UA_ByteString_copy(src: &sessionResponse->serverNonce, dst: &client->remoteNonce);
47227 res |= UA_NodeId_copy(src: &sessionResponse->authenticationToken, dst: &client->authenticationToken);
47228 if(res != UA_STATUSCODE_GOOD)
47229 goto cleanup;
47230
47231 /* Activate the new Session */
47232 client->sessionState = UA_SESSIONSTATE_CREATED;
47233
47234 cleanup:
47235 client->connectStatus = res;
47236 if(client->connectStatus != UA_STATUSCODE_GOOD)
47237 client->sessionState = UA_SESSIONSTATE_CLOSED;
47238}
47239
47240static UA_StatusCode
47241createSessionAsync(UA_Client *client) {
47242 UA_StatusCode retval = UA_STATUSCODE_GOOD;
47243 if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
47244 client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
47245 if(client->localNonce.length != UA_SESSION_LOCALNONCELENGTH) {
47246 UA_ByteString_clear(p: &client->localNonce);
47247 retval = UA_ByteString_allocBuffer(bs: &client->localNonce,
47248 UA_SESSION_LOCALNONCELENGTH);
47249 if(retval != UA_STATUSCODE_GOOD)
47250 return retval;
47251 }
47252 retval = client->channel.securityPolicy->symmetricModule.
47253 generateNonce(client->channel.securityPolicy->policyContext,
47254 &client->localNonce);
47255 if(retval != UA_STATUSCODE_GOOD)
47256 return retval;
47257 }
47258
47259 UA_CreateSessionRequest request;
47260 UA_CreateSessionRequest_init(p: &request);
47261 request.requestHeader.requestHandle = ++client->requestHandle;
47262 request.requestHeader.timestamp = UA_DateTime_now();
47263 request.requestHeader.timeoutHint = 10000;
47264 UA_ByteString_copy(src: &client->localNonce, dst: &request.clientNonce);
47265 request.requestedSessionTimeout = client->config.requestedSessionTimeout;
47266 request.maxResponseMessageSize = UA_INT32_MAX;
47267 UA_String_copy(src: &client->config.endpoint.endpointUrl, dst: &request.endpointUrl);
47268 UA_ApplicationDescription_copy(src: &client->config.clientDescription,
47269 dst: &request.clientDescription);
47270
47271 if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
47272 client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
47273 UA_ByteString_copy(src: &client->channel.securityPolicy->localCertificate,
47274 dst: &request.clientCertificate);
47275 }
47276
47277 retval = UA_Client_sendAsyncRequest(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
47278 callback: (UA_ClientAsyncServiceCallback)responseSessionCallback,
47279 responseType: &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE], NULL, NULL);
47280 UA_CreateSessionRequest_clear(p: &request);
47281
47282 if(retval == UA_STATUSCODE_GOOD)
47283 client->sessionState = UA_SESSIONSTATE_CREATE_REQUESTED;
47284 else
47285 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47286 msg: "CreateSession failed when sending the request with error code %s",
47287 UA_StatusCode_name(code: retval));
47288
47289 return retval;
47290}
47291
47292static UA_StatusCode
47293initConnect(UA_Client *client);
47294
47295UA_StatusCode
47296connectIterate(UA_Client *client, UA_UInt32 timeout) {
47297 UA_LOG_TRACE(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47298 msg: "Client connect iterate");
47299
47300 /* Already connected */
47301 if(client->sessionState == UA_SESSIONSTATE_ACTIVATED)
47302 return UA_STATUSCODE_GOOD;
47303
47304 /* Could not connect */
47305 if(client->connectStatus != UA_STATUSCODE_GOOD)
47306 return client->connectStatus;
47307
47308 /* The connection was already closed */
47309 if(client->channel.state == UA_SECURECHANNELSTATE_CLOSING) {
47310 client->connectStatus = UA_STATUSCODE_BADCONNECTIONCLOSED;
47311 return UA_STATUSCODE_BADCONNECTIONCLOSED;
47312 }
47313
47314 /* The connection is closed. Reset the SecureChannel and open a new TCP
47315 * connection */
47316 if(client->connection.state == UA_CONNECTIONSTATE_CLOSED)
47317 return initConnect(client);
47318
47319 /* Poll the connection status */
47320 if(client->connection.state == UA_CONNECTIONSTATE_OPENING) {
47321 client->connectStatus =
47322 client->config.pollConnectionFunc(&client->connection, timeout,
47323 &client->config.logger);
47324 return client->connectStatus;
47325 }
47326
47327 /* Attach the connection to the SecureChannel */
47328 if(!client->channel.connection)
47329 UA_Connection_attachSecureChannel(connection: &client->connection, channel: &client->channel);
47330
47331 /* Set the SecurityPolicy */
47332 if(!client->channel.securityPolicy) {
47333 client->channel.securityMode = client->config.endpoint.securityMode;
47334 if(client->channel.securityMode == UA_MESSAGESECURITYMODE_INVALID)
47335 client->channel.securityMode = UA_MESSAGESECURITYMODE_NONE;
47336
47337 UA_SecurityPolicy *sp = NULL;
47338 if(client->config.endpoint.securityPolicyUri.length == 0) {
47339 sp = getSecurityPolicy(client,
47340 policyUri: UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"));
47341 } else {
47342 sp = getSecurityPolicy(client, policyUri: client->config.endpoint.securityPolicyUri);
47343 }
47344 if(!sp) {
47345 client->connectStatus = UA_STATUSCODE_BADINTERNALERROR;
47346 return client->connectStatus;
47347 }
47348
47349 client->connectStatus =
47350 UA_SecureChannel_setSecurityPolicy(channel: &client->channel, securityPolicy: sp,
47351 remoteCertificate: &client->config.endpoint.serverCertificate);
47352 if(client->connectStatus != UA_STATUSCODE_GOOD)
47353 return client->connectStatus;
47354 }
47355
47356 /* Open the SecureChannel */
47357 switch(client->channel.state) {
47358 case UA_SECURECHANNELSTATE_FRESH:
47359 client->connectStatus = sendHELMessage(client);
47360 if(client->connectStatus == UA_STATUSCODE_GOOD) {
47361 client->channel.state = UA_SECURECHANNELSTATE_HEL_SENT;
47362 } else {
47363 client->connection.close(&client->connection);
47364 client->connection.free(&client->connection);
47365 }
47366 return client->connectStatus;
47367 case UA_SECURECHANNELSTATE_ACK_RECEIVED:
47368 client->connectStatus = sendOPNAsync(client, false);
47369 return client->connectStatus;
47370 case UA_SECURECHANNELSTATE_HEL_SENT:
47371 case UA_SECURECHANNELSTATE_OPN_SENT:
47372 client->connectStatus = receiveResponseAsync(client, timeout);
47373 return client->connectStatus;
47374 default:
47375 break;
47376 }
47377
47378 /* Call FindServers to see whether we need to reconnect with the correct
47379 * EndpointUrl */
47380 if(!client->findServersHandshake && client->discoveryUrl.length == 0) {
47381 client->connectStatus = requestFindServers(client);
47382 return client->connectStatus;
47383 }
47384
47385 /* FindServers was sent out, but we are still waiting for the response */
47386 if(client->discoveryUrl.length == 0) {
47387 receiveResponseAsync(client, timeout);
47388 return client->connectStatus;
47389 }
47390
47391 /* Have a SecureChannel but no session */
47392 if(client->noSession)
47393 return client->connectStatus;
47394
47395 /* Create and Activate the Session */
47396 switch(client->sessionState) {
47397 case UA_SESSIONSTATE_CLOSED:
47398 if(!endpointUnconfigured(client)) {
47399 client->connectStatus = createSessionAsync(client);
47400 return client->connectStatus;
47401 }
47402 if(!client->endpointsHandshake) {
47403 client->connectStatus = requestGetEndpoints(client);
47404 return client->connectStatus;
47405 }
47406 receiveResponseAsync(client, timeout);
47407 return client->connectStatus;
47408 case UA_SESSIONSTATE_CREATE_REQUESTED:
47409 case UA_SESSIONSTATE_ACTIVATE_REQUESTED:
47410 receiveResponseAsync(client, timeout);
47411 return client->connectStatus;
47412 case UA_SESSIONSTATE_CREATED:
47413 client->connectStatus = activateSessionAsync(client);
47414 return client->connectStatus;
47415 default:
47416 break;
47417 }
47418
47419 return client->connectStatus;
47420}
47421
47422/* The local ApplicationURI has to match the certificates of the
47423 * SecurityPolicies */
47424static void
47425verifyClientApplicationURI(const UA_Client *client) {
47426#if defined(UA_ENABLE_ENCRYPTION) && (UA_LOGLEVEL <= 400)
47427 for(size_t i = 0; i < client->config.securityPoliciesSize; i++) {
47428 UA_SecurityPolicy *sp = &client->config.securityPolicies[i];
47429 UA_StatusCode retval =
47430 client->config.certificateVerification.
47431 verifyApplicationURI(client->config.certificateVerification.context,
47432 &sp->localCertificate,
47433 &client->config.clientDescription.applicationUri);
47434 if(retval != UA_STATUSCODE_GOOD) {
47435 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47436 msg: "The configured ApplicationURI does not match the URI "
47437 "specified in the certificate for the SecurityPolicy %.*s",
47438 (int)sp->policyUri.length, sp->policyUri.data);
47439 }
47440 }
47441#endif
47442}
47443
47444static UA_StatusCode
47445client_configure_securechannel(void *application, UA_SecureChannel *channel,
47446 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
47447 // TODO: Verify if certificate is the same as configured in the client endpoint config
47448 return UA_STATUSCODE_GOOD;
47449}
47450
47451static UA_StatusCode
47452initConnect(UA_Client *client) {
47453 if(client->connection.state > UA_CONNECTIONSTATE_CLOSED) {
47454 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47455 msg: "Client already connected");
47456 return UA_STATUSCODE_GOOD;
47457 }
47458
47459 if(client->config.initConnectionFunc == NULL) {
47460 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47461 msg: "Client connection not configured");
47462 return UA_STATUSCODE_BADINTERNALERROR;
47463 }
47464
47465 /* Consistency check the client's own ApplicationURI */
47466 verifyClientApplicationURI(client);
47467
47468 /* Reset the connect status */
47469 client->connectStatus = UA_STATUSCODE_GOOD;
47470 client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
47471 client->endpointsHandshake = false;
47472
47473 /* Initialize the SecureChannel */
47474 UA_SecureChannel_init(channel: &client->channel, config: &client->config.localConnectionConfig);
47475 client->channel.certificateVerification = &client->config.certificateVerification;
47476 client->channel.processOPNHeader = client_configure_securechannel;
47477
47478 if(client->connection.free)
47479 client->connection.free(&client->connection);
47480
47481 /* Initialize the TCP connection */
47482 client->connection =
47483 client->config.initConnectionFunc(client->config.localConnectionConfig,
47484 client->endpointUrl, client->config.timeout,
47485 &client->config.logger);
47486 if(client->connection.state != UA_CONNECTIONSTATE_OPENING) {
47487 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47488 msg: "Could not open a TCP connection to %.*s",
47489 (int)client->endpointUrl.length, client->endpointUrl.data);
47490 client->connectStatus = UA_STATUSCODE_BADCONNECTIONCLOSED;
47491 closeSecureChannel(client);
47492 }
47493
47494 return client->connectStatus;
47495}
47496
47497UA_StatusCode
47498UA_Client_connectAsync(UA_Client *client, const char *endpointUrl) {
47499 /* Set the endpoint URL the client connects to */
47500 UA_String_clear(p: &client->endpointUrl);
47501 UA_String_clear(p: &client->discoveryUrl);
47502 client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
47503
47504 /* Open a Session when possible */
47505 client->noSession = false;
47506
47507 /* Connect Async */
47508 return initConnect(client);
47509}
47510
47511UA_StatusCode
47512UA_Client_connectSecureChannelAsync(UA_Client *client, const char *endpointUrl) {
47513 /* Set the endpoint URL the client connects to */
47514 UA_String_clear(p: &client->endpointUrl);
47515 UA_String_clear(p: &client->discoveryUrl);
47516 client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
47517
47518 /* Don't open a Session */
47519 client->noSession = true;
47520
47521 /* Connect Async */
47522 return initConnect(client);
47523}
47524
47525static UA_StatusCode
47526connectSync(UA_Client *client) {
47527 UA_DateTime now = UA_DateTime_nowMonotonic();
47528 UA_DateTime maxDate = now + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC);
47529
47530 UA_StatusCode retval = initConnect(client);
47531 if(retval != UA_STATUSCODE_GOOD)
47532 return retval;
47533
47534 while(retval == UA_STATUSCODE_GOOD) {
47535 if(!client->endpointsHandshake && !client->findServersHandshake &&
47536 client->discoveryUrl.length > 0 &&
47537 (client->sessionState == UA_SESSIONSTATE_ACTIVATED ||
47538 (client->noSession && client->channel.state == UA_SECURECHANNELSTATE_OPEN)))
47539 break;
47540 now = UA_DateTime_nowMonotonic();
47541 if(maxDate < now)
47542 return UA_STATUSCODE_BADTIMEOUT;
47543 retval = UA_Client_run_iterate(client,
47544 timeout: (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC));
47545 }
47546
47547 return retval;
47548}
47549
47550UA_StatusCode
47551UA_Client_connect(UA_Client *client, const char *endpointUrl) {
47552 /* Set the endpoint URL the client connects to */
47553 UA_String_clear(p: &client->endpointUrl);
47554 UA_String_clear(p: &client->discoveryUrl);
47555 client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
47556
47557 /* Open a Session when possible */
47558 client->noSession = false;
47559
47560 /* Connect Synchronous */
47561 return connectSync(client);
47562}
47563
47564UA_StatusCode
47565UA_Client_connectSecureChannel(UA_Client *client, const char *endpointUrl) {
47566 /* Set the endpoint URL the client connects to */
47567 UA_String_clear(p: &client->endpointUrl);
47568 UA_String_clear(p: &client->discoveryUrl);
47569 client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
47570
47571 /* Don't open a Session */
47572 client->noSession = true;
47573
47574 /* Connect Synchronous */
47575 return connectSync(client);
47576}
47577
47578/************************/
47579/* Close the Connection */
47580/************************/
47581
47582void
47583closeSecureChannel(UA_Client *client) {
47584 /* Send CLO if the SecureChannel is open */
47585 if(client->channel.state == UA_SECURECHANNELSTATE_OPEN) {
47586 UA_CloseSecureChannelRequest request;
47587 UA_CloseSecureChannelRequest_init(p: &request);
47588 request.requestHeader.requestHandle = ++client->requestHandle;
47589 request.requestHeader.timestamp = UA_DateTime_now();
47590 request.requestHeader.timeoutHint = 10000;
47591 request.requestHeader.authenticationToken = client->authenticationToken;
47592 UA_SecureChannel_sendSymmetricMessage(channel: &client->channel, requestId: ++client->requestId,
47593 messageType: UA_MESSAGETYPE_CLO, payload: &request,
47594 payloadType: &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
47595 }
47596
47597 /* Clean up */
47598 client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
47599 UA_SecureChannel_close(channel: &client->channel);
47600 if(client->connection.free)
47601 client->connection.free(&client->connection);
47602
47603 /* Set the Session to "Created" if it was "Activated" */
47604 if(client->sessionState > UA_SESSIONSTATE_CREATED)
47605 client->sessionState = UA_SESSIONSTATE_CREATED;
47606
47607 /* Delete outstanding async services - the RequestId is no longr valid. Do
47608 * this after setting the Session state. Otherwise we send out new Publish
47609 * Requests immediately. */
47610 UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSECURECHANNELCLOSED);
47611}
47612
47613static void
47614sendCloseSession(UA_Client *client) {
47615 /* Set before sending the message to prevent recursion */
47616 client->sessionState = UA_SESSIONSTATE_CLOSING;
47617
47618 UA_CloseSessionRequest request;
47619 UA_CloseSessionRequest_init(p: &request);
47620 request.requestHeader.timestamp = UA_DateTime_now();
47621 request.requestHeader.timeoutHint = 10000;
47622 request.deleteSubscriptions = true;
47623 UA_CloseSessionResponse response;
47624 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
47625 response: &response, responseType: &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
47626 UA_CloseSessionRequest_clear(p: &request);
47627 UA_CloseSessionResponse_clear(p: &response);
47628}
47629
47630static void
47631closeSession(UA_Client *client) {
47632 /* Is a session established? */
47633 if(client->sessionState == UA_SESSIONSTATE_ACTIVATED)
47634 sendCloseSession(client);
47635
47636 UA_NodeId_clear(p: &client->authenticationToken);
47637 client->requestHandle = 0;
47638 client->sessionState = UA_SESSIONSTATE_CLOSED;
47639
47640#ifdef UA_ENABLE_SUBSCRIPTIONS
47641 /* We need to clean up the subscriptions */
47642 UA_Client_Subscriptions_clean(client);
47643#endif
47644
47645 /* Reset so the next async connect creates a session by default */
47646 client->noSession = false;
47647
47648 /* Delete outstanding async services */
47649 UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSESSIONCLOSED);
47650
47651#ifdef UA_ENABLE_SUBSCRIPTIONS
47652 client->currentlyOutStandingPublishRequests = 0;
47653#endif
47654}
47655
47656static void
47657closeSessionCallback(UA_Client *client, void *userdata,
47658 UA_UInt32 requestId, void *response) {
47659 closeSession(client);
47660 closeSecureChannel(client);
47661 notifyClientState(client);
47662}
47663
47664UA_StatusCode UA_EXPORT
47665UA_Client_disconnectAsync(UA_Client *client) {
47666 /* Set before sending the message to prevent recursion */
47667 client->sessionState = UA_SESSIONSTATE_CLOSING;
47668
47669 UA_CloseSessionRequest request;
47670 UA_CloseSessionRequest_init(p: &request);
47671 request.requestHeader.timestamp = UA_DateTime_now();
47672 request.requestHeader.timeoutHint = 10000;
47673 request.deleteSubscriptions = true;
47674 UA_StatusCode res =
47675 UA_Client_sendAsyncRequest(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
47676 callback: (UA_ClientAsyncServiceCallback)closeSessionCallback,
47677 responseType: &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE], NULL, NULL);
47678 notifyClientState(client);
47679 return res;
47680}
47681
47682UA_StatusCode
47683UA_Client_disconnectSecureChannel(UA_Client *client) {
47684 closeSecureChannel(client);
47685 notifyClientState(client);
47686 return UA_STATUSCODE_GOOD;
47687}
47688
47689UA_StatusCode
47690UA_Client_disconnect(UA_Client *client) {
47691 closeSession(client);
47692 closeSecureChannel(client);
47693 notifyClientState(client);
47694 return UA_STATUSCODE_GOOD;
47695}
47696
47697
47698/**** amalgamated original file "/src/client/ua_client_discovery.c" ****/
47699
47700/* This Source Code Form is subject to the terms of the Mozilla Public
47701 * License, v. 2.0. If a copy of the MPL was not distributed with this
47702 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
47703 *
47704 * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
47705 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
47706 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
47707 */
47708
47709
47710/* Helper method for additional warnings */
47711void
47712Client_warnEndpointsResult(UA_Client *client,
47713 const UA_GetEndpointsResponse *response,
47714 const UA_String *endpointUrl) {
47715 if(response->endpointsSize == 0) {
47716 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47717 msg: "The server did not return any endpoints. "
47718 "Did you use the correct endpointUrl?");
47719 return;
47720 }
47721
47722 if(!UA_String_equal(s1: endpointUrl, s2: &response->endpoints[0].endpointUrl) ||
47723 (response->endpoints[0].server.discoveryUrlsSize > 0 &&
47724 !UA_String_equal(s1: endpointUrl, s2: &response->endpoints[0].server.discoveryUrls[0]))) {
47725 UA_String *betterUrl = &response->endpoints[0].endpointUrl;
47726 if(response->endpoints[0].server.discoveryUrlsSize > 0)
47727 betterUrl = &response->endpoints[0].server.discoveryUrls[0];
47728 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47729 msg: "The server returned Endpoints with a different EndpointUrl %.*s than was "
47730 "used to initialize the connection: %.*s. Some servers require a complete "
47731 "match of the EndpointUrl/DiscoveryUrl (including the path) "
47732 "to return all endpoints.",
47733 (int)betterUrl->length, betterUrl->data,
47734 (int)endpointUrl->length, endpointUrl->data);
47735 }
47736}
47737
47738/* Gets a list of endpoints. Memory is allocated for endpointDescription array */
47739static UA_StatusCode
47740UA_Client_getEndpointsInternal(UA_Client *client, const UA_String endpointUrl,
47741 size_t *endpointDescriptionsSize,
47742 UA_EndpointDescription **endpointDescriptions) {
47743 UA_GetEndpointsRequest request;
47744 UA_GetEndpointsRequest_init(p: &request);
47745 request.requestHeader.timestamp = UA_DateTime_now();
47746 request.requestHeader.timeoutHint = 10000;
47747 // assume the endpointurl outlives the service call
47748 request.endpointUrl = endpointUrl;
47749
47750 UA_GetEndpointsResponse response;
47751 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
47752 response: &response, responseType: &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
47753
47754 if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
47755 UA_StatusCode retval = response.responseHeader.serviceResult;
47756 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47757 msg: "GetEndpointRequest failed with error code %s",
47758 UA_StatusCode_name(code: retval));
47759 UA_GetEndpointsResponse_clear(p: &response);
47760 return retval;
47761 }
47762
47763 *endpointDescriptions = response.endpoints;
47764 *endpointDescriptionsSize = response.endpointsSize;
47765 response.endpoints = NULL;
47766 response.endpointsSize = 0;
47767 UA_GetEndpointsResponse_clear(p: &response);
47768 return UA_STATUSCODE_GOOD;
47769}
47770
47771UA_StatusCode
47772UA_Client_getEndpoints(UA_Client *client, const char *serverUrl,
47773 size_t* endpointDescriptionsSize,
47774 UA_EndpointDescription** endpointDescriptions) {
47775 UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
47776 /* Client is already connected to a different server */
47777 if(connected && strncmp(s1: (const char*)client->config.endpoint.endpointUrl.data, s2: serverUrl,
47778 n: client->config.endpoint.endpointUrl.length) != 0) {
47779 return UA_STATUSCODE_BADINVALIDARGUMENT;
47780 }
47781
47782 UA_StatusCode retval;
47783 const UA_String url = UA_STRING(chars: (char*)(uintptr_t)serverUrl);
47784 if(!connected) {
47785 retval = UA_Client_connectSecureChannel(client, endpointUrl: serverUrl);
47786 if(retval != UA_STATUSCODE_GOOD)
47787 return retval;
47788 }
47789 retval = UA_Client_getEndpointsInternal(client, endpointUrl: url, endpointDescriptionsSize,
47790 endpointDescriptions);
47791
47792 if(!connected)
47793 UA_Client_disconnect(client);
47794 return retval;
47795}
47796
47797UA_StatusCode
47798UA_Client_findServers(UA_Client *client, const char *serverUrl,
47799 size_t serverUrisSize, UA_String *serverUris,
47800 size_t localeIdsSize, UA_String *localeIds,
47801 size_t *registeredServersSize,
47802 UA_ApplicationDescription **registeredServers) {
47803 UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
47804 /* Client is already connected to a different server */
47805 if(connected && strncmp(s1: (const char*)client->config.endpoint.endpointUrl.data, s2: serverUrl,
47806 n: client->config.endpoint.endpointUrl.length) != 0) {
47807 return UA_STATUSCODE_BADINVALIDARGUMENT;
47808 }
47809
47810 UA_StatusCode retval;
47811 if(!connected) {
47812 retval = UA_Client_connectSecureChannel(client, endpointUrl: serverUrl);
47813 if(retval != UA_STATUSCODE_GOOD)
47814 return retval;
47815 }
47816
47817 /* Prepare the request */
47818 UA_FindServersRequest request;
47819 UA_FindServersRequest_init(p: &request);
47820 request.serverUrisSize = serverUrisSize;
47821 request.serverUris = serverUris;
47822 request.localeIdsSize = localeIdsSize;
47823 request.localeIds = localeIds;
47824
47825 /* Send the request */
47826 UA_FindServersResponse response;
47827 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST],
47828 response: &response, responseType: &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
47829
47830 /* Process the response */
47831 retval = response.responseHeader.serviceResult;
47832 if(retval == UA_STATUSCODE_GOOD) {
47833 *registeredServersSize = response.serversSize;
47834 *registeredServers = response.servers;
47835 response.serversSize = 0;
47836 response.servers = NULL;
47837 } else {
47838 *registeredServersSize = 0;
47839 *registeredServers = NULL;
47840 }
47841
47842 /* Clean up */
47843 UA_FindServersResponse_clear(p: &response);
47844 if(!connected)
47845 UA_Client_disconnect(client);
47846 return retval;
47847}
47848
47849#ifdef UA_ENABLE_DISCOVERY
47850
47851UA_StatusCode
47852UA_Client_findServersOnNetwork(UA_Client *client, const char *serverUrl,
47853 UA_UInt32 startingRecordId, UA_UInt32 maxRecordsToReturn,
47854 size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter,
47855 size_t *serverOnNetworkSize, UA_ServerOnNetwork **serverOnNetwork) {
47856 UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
47857 /* Client is already connected to a different server */
47858 if(connected && strncmp((const char*)client->config.endpoint.endpointUrl.data, serverUrl,
47859 client->config.endpoint.endpointUrl.length) != 0) {
47860 return UA_STATUSCODE_BADINVALIDARGUMENT;
47861 }
47862
47863 UA_StatusCode retval;
47864 if(!connected) {
47865 retval = UA_Client_connectSecureChannel(client, serverUrl);
47866 if(retval != UA_STATUSCODE_GOOD)
47867 return retval;
47868 }
47869
47870 /* Prepare the request */
47871 UA_FindServersOnNetworkRequest request;
47872 UA_FindServersOnNetworkRequest_init(&request);
47873 request.startingRecordId = startingRecordId;
47874 request.maxRecordsToReturn = maxRecordsToReturn;
47875 request.serverCapabilityFilterSize = serverCapabilityFilterSize;
47876 request.serverCapabilityFilter = serverCapabilityFilter;
47877
47878 /* Send the request */
47879 UA_FindServersOnNetworkResponse response;
47880 __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST],
47881 &response, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE]);
47882
47883 /* Process the response */
47884 retval = response.responseHeader.serviceResult;
47885 if(retval == UA_STATUSCODE_GOOD) {
47886 *serverOnNetworkSize = response.serversSize;
47887 *serverOnNetwork = response.servers;
47888 response.serversSize = 0;
47889 response.servers = NULL;
47890 } else {
47891 *serverOnNetworkSize = 0;
47892 *serverOnNetwork = NULL;
47893 }
47894
47895 /* Clean up */
47896 UA_FindServersOnNetworkResponse_clear(&response);
47897 if(!connected)
47898 UA_Client_disconnect(client);
47899 return retval;
47900}
47901
47902#endif
47903
47904/**** amalgamated original file "/src/client/ua_client_highlevel.c" ****/
47905
47906/* This Source Code Form is subject to the terms of the Mozilla Public
47907 * License, v. 2.0. If a copy of the MPL was not distributed with this
47908 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
47909 *
47910 * Copyright 2015-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
47911 * Copyright 2015 (c) Oleksiy Vasylyev
47912 * Copyright 2017 (c) Florian Palm
47913 * Copyright 2016 (c) Chris Iatrou
47914 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
47915 * Copyright 2018 (c) Fabian Arndt
47916 * Copyright 2018 (c) Peter Rustler, basyskom GmbH
47917 */
47918
47919
47920/* The highlevel client API is an "outer onion layer". This file does not
47921 * include ua_client_internal.h on purpose. */
47922
47923UA_StatusCode
47924UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri,
47925 UA_UInt16 *namespaceIndex) {
47926 UA_ReadRequest request;
47927 UA_ReadRequest_init(p: &request);
47928 UA_ReadValueId id;
47929 UA_ReadValueId_init(p: &id);
47930 id.attributeId = UA_ATTRIBUTEID_VALUE;
47931 id.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY);
47932 request.nodesToRead = &id;
47933 request.nodesToReadSize = 1;
47934
47935 UA_ReadResponse response = UA_Client_Service_read(client, request);
47936
47937 UA_StatusCode retval = UA_STATUSCODE_GOOD;
47938 if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
47939 retval = response.responseHeader.serviceResult;
47940 else if(response.resultsSize != 1 || !response.results[0].hasValue)
47941 retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
47942 else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING])
47943 retval = UA_STATUSCODE_BADTYPEMISMATCH;
47944
47945 if(retval != UA_STATUSCODE_GOOD) {
47946 UA_ReadResponse_clear(p: &response);
47947 return retval;
47948 }
47949
47950 retval = UA_STATUSCODE_BADNOTFOUND;
47951 UA_String *ns = (UA_String *)response.results[0].value.data;
47952 for(size_t i = 0; i < response.results[0].value.arrayLength; ++i) {
47953 if(UA_String_equal(s1: namespaceUri, s2: &ns[i])) {
47954 *namespaceIndex = (UA_UInt16)i;
47955 retval = UA_STATUSCODE_GOOD;
47956 break;
47957 }
47958 }
47959
47960 UA_ReadResponse_clear(p: &response);
47961 return retval;
47962}
47963
47964UA_StatusCode
47965UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId,
47966 UA_NodeIteratorCallback callback, void *handle) {
47967 UA_BrowseRequest bReq;
47968 UA_BrowseRequest_init(p: &bReq);
47969 bReq.requestedMaxReferencesPerNode = 0;
47970 bReq.nodesToBrowse = UA_BrowseDescription_new();
47971 bReq.nodesToBrowseSize = 1;
47972 UA_NodeId_copy(src: &parentNodeId, dst: &bReq.nodesToBrowse[0].nodeId);
47973 bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything
47974 bReq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_BOTH;
47975
47976 UA_BrowseResponse bResp = UA_Client_Service_browse(client, request: bReq);
47977
47978 UA_StatusCode retval = bResp.responseHeader.serviceResult;
47979 if(retval == UA_STATUSCODE_GOOD) {
47980 for(size_t i = 0; i < bResp.resultsSize; ++i) {
47981 for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) {
47982 UA_ReferenceDescription *ref = &bResp.results[i].references[j];
47983 retval |= callback(ref->nodeId.nodeId, !ref->isForward,
47984 ref->referenceTypeId, handle);
47985 }
47986 }
47987 }
47988
47989 UA_BrowseRequest_clear(p: &bReq);
47990 UA_BrowseResponse_clear(p: &bResp);
47991 return retval;
47992}
47993
47994/*******************/
47995/* Node Management */
47996/*******************/
47997
47998UA_StatusCode
47999UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId,
48000 const UA_NodeId referenceTypeId, UA_Boolean isForward,
48001 const UA_String targetServerUri,
48002 const UA_ExpandedNodeId targetNodeId,
48003 UA_NodeClass targetNodeClass) {
48004 UA_AddReferencesItem item;
48005 UA_AddReferencesItem_init(p: &item);
48006 item.sourceNodeId = sourceNodeId;
48007 item.referenceTypeId = referenceTypeId;
48008 item.isForward = isForward;
48009 item.targetServerUri = targetServerUri;
48010 item.targetNodeId = targetNodeId;
48011 item.targetNodeClass = targetNodeClass;
48012 UA_AddReferencesRequest request;
48013 UA_AddReferencesRequest_init(p: &request);
48014 request.referencesToAdd = &item;
48015 request.referencesToAddSize = 1;
48016 UA_AddReferencesResponse response = UA_Client_Service_addReferences(client, request);
48017 UA_StatusCode retval = response.responseHeader.serviceResult;
48018 if(retval != UA_STATUSCODE_GOOD) {
48019 UA_AddReferencesResponse_clear(p: &response);
48020 return retval;
48021 }
48022 if(response.resultsSize != 1) {
48023 UA_AddReferencesResponse_clear(p: &response);
48024 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48025 }
48026 retval = response.results[0];
48027 UA_AddReferencesResponse_clear(p: &response);
48028 return retval;
48029}
48030
48031UA_StatusCode
48032UA_Client_deleteReference(UA_Client *client, const UA_NodeId sourceNodeId,
48033 const UA_NodeId referenceTypeId, UA_Boolean isForward,
48034 const UA_ExpandedNodeId targetNodeId,
48035 UA_Boolean deleteBidirectional) {
48036 UA_DeleteReferencesItem item;
48037 UA_DeleteReferencesItem_init(p: &item);
48038 item.sourceNodeId = sourceNodeId;
48039 item.referenceTypeId = referenceTypeId;
48040 item.isForward = isForward;
48041 item.targetNodeId = targetNodeId;
48042 item.deleteBidirectional = deleteBidirectional;
48043 UA_DeleteReferencesRequest request;
48044 UA_DeleteReferencesRequest_init(p: &request);
48045 request.referencesToDelete = &item;
48046 request.referencesToDeleteSize = 1;
48047 UA_DeleteReferencesResponse response = UA_Client_Service_deleteReferences(client, request);
48048 UA_StatusCode retval = response.responseHeader.serviceResult;
48049 if(retval != UA_STATUSCODE_GOOD) {
48050 UA_DeleteReferencesResponse_clear(p: &response);
48051 return retval;
48052 }
48053 if(response.resultsSize != 1) {
48054 UA_DeleteReferencesResponse_clear(p: &response);
48055 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48056 }
48057 retval = response.results[0];
48058 UA_DeleteReferencesResponse_clear(p: &response);
48059 return retval;
48060}
48061
48062UA_StatusCode
48063UA_Client_deleteNode(UA_Client *client, const UA_NodeId nodeId,
48064 UA_Boolean deleteTargetReferences) {
48065 UA_DeleteNodesItem item;
48066 UA_DeleteNodesItem_init(p: &item);
48067 item.nodeId = nodeId;
48068 item.deleteTargetReferences = deleteTargetReferences;
48069 UA_DeleteNodesRequest request;
48070 UA_DeleteNodesRequest_init(p: &request);
48071 request.nodesToDelete = &item;
48072 request.nodesToDeleteSize = 1;
48073 UA_DeleteNodesResponse response = UA_Client_Service_deleteNodes(client, request);
48074 UA_StatusCode retval = response.responseHeader.serviceResult;
48075 if(retval != UA_STATUSCODE_GOOD) {
48076 UA_DeleteNodesResponse_clear(p: &response);
48077 return retval;
48078 }
48079 if(response.resultsSize != 1) {
48080 UA_DeleteNodesResponse_clear(p: &response);
48081 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48082 }
48083 retval = response.results[0];
48084 UA_DeleteNodesResponse_clear(p: &response);
48085 return retval;
48086}
48087
48088UA_StatusCode
48089__UA_Client_addNode(UA_Client *client, const UA_NodeClass nodeClass,
48090 const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
48091 const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
48092 const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
48093 const UA_DataType *attributeType, UA_NodeId *outNewNodeId) {
48094 UA_AddNodesRequest request;
48095 UA_AddNodesRequest_init(p: &request);
48096 UA_AddNodesItem item;
48097 UA_AddNodesItem_init(p: &item);
48098 item.parentNodeId.nodeId = parentNodeId;
48099 item.referenceTypeId = referenceTypeId;
48100 item.requestedNewNodeId.nodeId = requestedNewNodeId;
48101 item.browseName = browseName;
48102 item.nodeClass = nodeClass;
48103 item.typeDefinition.nodeId = typeDefinition;
48104 item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
48105 item.nodeAttributes.content.decoded.type = attributeType;
48106 item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)attr; // hack. is not written into.
48107 request.nodesToAdd = &item;
48108 request.nodesToAddSize = 1;
48109 UA_AddNodesResponse response = UA_Client_Service_addNodes(client, request);
48110
48111 UA_StatusCode retval = response.responseHeader.serviceResult;
48112 if(retval != UA_STATUSCODE_GOOD) {
48113 UA_AddNodesResponse_clear(p: &response);
48114 return retval;
48115 }
48116
48117 if(response.resultsSize != 1) {
48118 UA_AddNodesResponse_clear(p: &response);
48119 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48120 }
48121
48122 /* Move the id of the created node */
48123 retval = response.results[0].statusCode;
48124 if(retval == UA_STATUSCODE_GOOD && outNewNodeId) {
48125 *outNewNodeId = response.results[0].addedNodeId;
48126 UA_NodeId_init(p: &response.results[0].addedNodeId);
48127 }
48128
48129 UA_AddNodesResponse_clear(p: &response);
48130 return retval;
48131}
48132
48133/********/
48134/* Call */
48135/********/
48136
48137#ifdef UA_ENABLE_METHODCALLS
48138
48139UA_StatusCode
48140UA_Client_call(UA_Client *client, const UA_NodeId objectId,
48141 const UA_NodeId methodId, size_t inputSize,
48142 const UA_Variant *input, size_t *outputSize,
48143 UA_Variant **output) {
48144 /* Set up the request */
48145 UA_CallRequest request;
48146 UA_CallRequest_init(p: &request);
48147 UA_CallMethodRequest item;
48148 UA_CallMethodRequest_init(p: &item);
48149 item.methodId = methodId;
48150 item.objectId = objectId;
48151 item.inputArguments = (UA_Variant *)(void*)(uintptr_t)input; // cast const...
48152 item.inputArgumentsSize = inputSize;
48153 request.methodsToCall = &item;
48154 request.methodsToCallSize = 1;
48155
48156 /* Call the service */
48157 UA_CallResponse response = UA_Client_Service_call(client, request);
48158 UA_StatusCode retval = response.responseHeader.serviceResult;
48159 if(retval == UA_STATUSCODE_GOOD) {
48160 if(response.resultsSize == 1)
48161 retval = response.results[0].statusCode;
48162 else
48163 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48164 }
48165 if(retval != UA_STATUSCODE_GOOD) {
48166 UA_CallResponse_clear(p: &response);
48167 return retval;
48168 }
48169
48170 /* Move the output arguments */
48171 if(output != NULL && outputSize != NULL) {
48172 *output = response.results[0].outputArguments;
48173 *outputSize = response.results[0].outputArgumentsSize;
48174 response.results[0].outputArguments = NULL;
48175 response.results[0].outputArgumentsSize = 0;
48176 }
48177 UA_CallResponse_clear(p: &response);
48178 return retval;
48179}
48180
48181#endif
48182
48183/********************/
48184/* Write Attributes */
48185/********************/
48186
48187UA_StatusCode
48188__UA_Client_writeAttribute(UA_Client *client, const UA_NodeId *nodeId,
48189 UA_AttributeId attributeId, const void *in,
48190 const UA_DataType *inDataType) {
48191 if(!in)
48192 return UA_STATUSCODE_BADTYPEMISMATCH;
48193
48194 UA_WriteValue wValue;
48195 UA_WriteValue_init(p: &wValue);
48196 wValue.nodeId = *nodeId;
48197 wValue.attributeId = attributeId;
48198 if(attributeId == UA_ATTRIBUTEID_VALUE)
48199 wValue.value.value = *(const UA_Variant*)in;
48200 else
48201 /* hack. is never written into. */
48202 UA_Variant_setScalar(v: &wValue.value.value, p: (void*)(uintptr_t)in, type: inDataType);
48203 wValue.value.hasValue = true;
48204 UA_WriteRequest wReq;
48205 UA_WriteRequest_init(p: &wReq);
48206 wReq.nodesToWrite = &wValue;
48207 wReq.nodesToWriteSize = 1;
48208
48209 UA_WriteResponse wResp = UA_Client_Service_write(client, request: wReq);
48210
48211 UA_StatusCode retval = wResp.responseHeader.serviceResult;
48212 if(retval == UA_STATUSCODE_GOOD) {
48213 if(wResp.resultsSize == 1)
48214 retval = wResp.results[0];
48215 else
48216 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48217 }
48218
48219 UA_WriteResponse_clear(p: &wResp);
48220 return retval;
48221}
48222
48223UA_StatusCode
48224UA_Client_writeArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
48225 size_t newArrayDimensionsSize,
48226 const UA_UInt32 *newArrayDimensions) {
48227 if(!newArrayDimensions)
48228 return UA_STATUSCODE_BADTYPEMISMATCH;
48229
48230 UA_WriteValue wValue;
48231 UA_WriteValue_init(p: &wValue);
48232 wValue.nodeId = nodeId;
48233 wValue.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
48234 UA_Variant_setArray(v: &wValue.value.value, array: (void*)(uintptr_t)newArrayDimensions,
48235 arraySize: newArrayDimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]);
48236 wValue.value.hasValue = true;
48237 UA_WriteRequest wReq;
48238 UA_WriteRequest_init(p: &wReq);
48239 wReq.nodesToWrite = &wValue;
48240 wReq.nodesToWriteSize = 1;
48241
48242 UA_WriteResponse wResp = UA_Client_Service_write(client, request: wReq);
48243
48244 UA_StatusCode retval = wResp.responseHeader.serviceResult;
48245 if(retval == UA_STATUSCODE_GOOD) {
48246 if(wResp.resultsSize == 1)
48247 retval = wResp.results[0];
48248 else
48249 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48250 }
48251 UA_WriteResponse_clear(p: &wResp);
48252 return retval;
48253}
48254
48255/*******************/
48256/* Read Attributes */
48257/*******************/
48258
48259UA_StatusCode
48260__UA_Client_readAttribute(UA_Client *client, const UA_NodeId *nodeId,
48261 UA_AttributeId attributeId, void *out,
48262 const UA_DataType *outDataType) {
48263 UA_ReadValueId item;
48264 UA_ReadValueId_init(p: &item);
48265 item.nodeId = *nodeId;
48266 item.attributeId = attributeId;
48267 UA_ReadRequest request;
48268 UA_ReadRequest_init(p: &request);
48269 request.nodesToRead = &item;
48270 request.nodesToReadSize = 1;
48271 UA_ReadResponse response = UA_Client_Service_read(client, request);
48272 UA_StatusCode retval = response.responseHeader.serviceResult;
48273 if(retval == UA_STATUSCODE_GOOD) {
48274 if(response.resultsSize == 1)
48275 retval = response.results[0].status;
48276 else
48277 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48278 }
48279 if(!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD)) {
48280 UA_ReadResponse_clear(p: &response);
48281 return retval;
48282 }
48283
48284 /* Set the StatusCode */
48285 UA_DataValue *res = response.results;
48286 if(res->hasStatus)
48287 retval = res->status;
48288
48289 /* Return early of no value is given */
48290 if(!res->hasValue) {
48291 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48292 UA_ReadResponse_clear(p: &response);
48293 return retval;
48294 }
48295
48296 /* Copy value into out */
48297 if(attributeId == UA_ATTRIBUTEID_VALUE) {
48298 memcpy(dest: out, src: &res->value, n: sizeof(UA_Variant));
48299 UA_Variant_init(p: &res->value);
48300 } else if(attributeId == UA_ATTRIBUTEID_NODECLASS) {
48301 memcpy(dest: out, src: (UA_NodeClass*)res->value.data, n: sizeof(UA_NodeClass));
48302 } else if(UA_Variant_isScalar(v: &res->value) &&
48303 res->value.type == outDataType) {
48304 memcpy(dest: out, src: res->value.data, n: res->value.type->memSize);
48305 UA_free(ptr: res->value.data);
48306 res->value.data = NULL;
48307 } else {
48308 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48309 }
48310
48311 UA_ReadResponse_clear(p: &response);
48312 return retval;
48313}
48314
48315static UA_StatusCode
48316processReadArrayDimensionsResult(UA_ReadResponse *response,
48317 UA_UInt32 **outArrayDimensions,
48318 size_t *outArrayDimensionsSize) {
48319 UA_StatusCode retval = response->responseHeader.serviceResult;
48320 if(retval != UA_STATUSCODE_GOOD)
48321 return retval;
48322
48323 if(response->resultsSize != 1)
48324 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48325
48326 retval = response->results[0].status;
48327 if(!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD))
48328 return retval;
48329
48330 UA_DataValue *res = &response->results[0];
48331 if(!res->hasValue ||
48332 UA_Variant_isScalar(v: &res->value) ||
48333 res->value.type != &UA_TYPES[UA_TYPES_UINT32])
48334 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48335
48336 /* Move results */
48337 *outArrayDimensions = (UA_UInt32*)res->value.data;
48338 *outArrayDimensionsSize = res->value.arrayLength;
48339 res->value.data = NULL;
48340 res->value.arrayLength = 0;
48341 return UA_STATUSCODE_GOOD;
48342}
48343
48344UA_StatusCode
48345UA_Client_readArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
48346 size_t *outArrayDimensionsSize,
48347 UA_UInt32 **outArrayDimensions) {
48348 UA_ReadValueId item;
48349 UA_ReadValueId_init(p: &item);
48350 item.nodeId = nodeId;
48351 item.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
48352 UA_ReadRequest request;
48353 UA_ReadRequest_init(p: &request);
48354 request.nodesToRead = &item;
48355 request.nodesToReadSize = 1;
48356
48357 UA_ReadResponse response = UA_Client_Service_read(client, request);
48358 UA_StatusCode retval = processReadArrayDimensionsResult(response: &response, outArrayDimensions,
48359 outArrayDimensionsSize);
48360 UA_ReadResponse_clear(p: &response);
48361 return retval;
48362}
48363
48364/*********************/
48365/* Historical Access */
48366/*********************/
48367#ifdef UA_ENABLE_HISTORIZING
48368static UA_HistoryReadResponse
48369__UA_Client_HistoryRead(UA_Client *client, const UA_NodeId *nodeId,
48370 UA_ExtensionObject* details, UA_String indexRange,
48371 UA_TimestampsToReturn timestampsToReturn,
48372 UA_ByteString continuationPoint, UA_Boolean releaseConti) {
48373
48374 UA_HistoryReadValueId item;
48375 UA_HistoryReadValueId_init(p: &item);
48376
48377 item.nodeId = *nodeId;
48378 item.indexRange = indexRange;
48379 item.continuationPoint = continuationPoint;
48380 item.dataEncoding = UA_QUALIFIEDNAME(nsIndex: 0, chars: "Default Binary");
48381
48382 UA_HistoryReadRequest request;
48383 UA_HistoryReadRequest_init(p: &request);
48384
48385 request.nodesToRead = &item;
48386 request.nodesToReadSize = 1;
48387 request.timestampsToReturn = timestampsToReturn; // Defaults to Source
48388 request.releaseContinuationPoints = releaseConti; // No values are returned, if true
48389
48390 /* Build ReadDetails */
48391 request.historyReadDetails = *details;
48392
48393 return UA_Client_Service_historyRead(client, request);
48394}
48395
48396static UA_StatusCode
48397__UA_Client_HistoryRead_service(UA_Client *client, const UA_NodeId *nodeId,
48398 const UA_HistoricalIteratorCallback callback,
48399 UA_ExtensionObject *details, UA_String indexRange,
48400 UA_TimestampsToReturn timestampsToReturn,
48401 void *callbackContext) {
48402
48403 UA_ByteString continuationPoint = UA_BYTESTRING_NULL;
48404 UA_Boolean continuationAvail = false;
48405 UA_Boolean fetchMore = false;
48406 UA_StatusCode retval = UA_STATUSCODE_GOOD;
48407
48408 do {
48409 /* We release the continuation point, if no more data is requested by the user */
48410 UA_Boolean cleanup = !fetchMore && continuationAvail;
48411 UA_HistoryReadResponse response =
48412 __UA_Client_HistoryRead(client, nodeId, details, indexRange, timestampsToReturn, continuationPoint, releaseConti: cleanup);
48413
48414 if (cleanup) {
48415 retval = response.responseHeader.serviceResult;
48416cleanup: UA_HistoryReadResponse_clear(p: &response);
48417 UA_ByteString_clear(p: &continuationPoint);
48418 return retval;
48419 }
48420
48421 retval = response.responseHeader.serviceResult;
48422 if (retval == UA_STATUSCODE_GOOD) {
48423 if (response.resultsSize == 1)
48424 retval = response.results[0].statusCode;
48425 else
48426 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48427 }
48428 if (!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD))
48429 goto cleanup;
48430
48431 UA_HistoryReadResult *res = response.results;
48432
48433 /* Clear old and check / store new continuation point */
48434 UA_ByteString_clear(p: &continuationPoint);
48435 UA_ByteString_copy(src: &res->continuationPoint, dst: &continuationPoint);
48436 continuationAvail = !UA_ByteString_equal(string1: &continuationPoint, string2: &UA_BYTESTRING_NULL);
48437
48438 /* Client callback with possibility to request further values */
48439 fetchMore = callback(client, nodeId, continuationAvail, &res->historyData, callbackContext);
48440
48441 /* Regular cleanup */
48442 UA_HistoryReadResponse_clear(p: &response);
48443 } while (continuationAvail);
48444
48445 return retval;
48446}
48447
48448#ifdef UA_ENABLE_EXPERIMENTAL_HISTORIZING
48449UA_StatusCode
48450UA_Client_HistoryRead_events(UA_Client *client, const UA_NodeId *nodeId,
48451 const UA_HistoricalIteratorCallback callback,
48452 UA_DateTime startTime, UA_DateTime endTime,
48453 UA_String indexRange, const UA_EventFilter filter, UA_UInt32 numValuesPerNode,
48454 UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
48455
48456 UA_ReadEventDetails details;
48457 UA_ReadEventDetails_init(p: &details);
48458 details.filter = filter;
48459
48460 // At least two of the following parameters must be set
48461 details.numValuesPerNode = numValuesPerNode; // 0 = return all / max server is capable of
48462 details.startTime = startTime;
48463 details.endTime = endTime;
48464
48465 UA_ExtensionObject detailsExtensionObject;
48466 UA_ExtensionObject_init(p: &detailsExtensionObject);
48467 detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READEVENTDETAILS];
48468 detailsExtensionObject.content.decoded.data = &details;
48469 detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED;
48470
48471 return __UA_Client_HistoryRead_service(client, nodeId, callback, details: &detailsExtensionObject,
48472 indexRange, timestampsToReturn, callbackContext);
48473}
48474#endif // UA_ENABLE_EXPERIMENTAL_HISTORIZING
48475
48476static UA_StatusCode
48477__UA_Client_HistoryRead_service_rawMod(UA_Client *client, const UA_NodeId *nodeId,
48478 const UA_HistoricalIteratorCallback callback,
48479 UA_DateTime startTime,UA_DateTime endTime,
48480 UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode,
48481 UA_Boolean readModified, UA_TimestampsToReturn timestampsToReturn,
48482 void *callbackContext) {
48483
48484 UA_ReadRawModifiedDetails details;
48485 UA_ReadRawModifiedDetails_init(p: &details);
48486 details.isReadModified = readModified; // Return only modified values
48487 details.returnBounds = returnBounds; // Return values pre / post given range
48488
48489 // At least two of the following parameters must be set
48490 details.numValuesPerNode = numValuesPerNode; // 0 = return all / max server is capable of
48491 details.startTime = startTime;
48492 details.endTime = endTime;
48493
48494 UA_ExtensionObject detailsExtensionObject;
48495 UA_ExtensionObject_init(p: &detailsExtensionObject);
48496 detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS];
48497 detailsExtensionObject.content.decoded.data = &details;
48498 detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED;
48499
48500 return __UA_Client_HistoryRead_service(client, nodeId, callback,
48501 details: &detailsExtensionObject, indexRange,
48502 timestampsToReturn, callbackContext);
48503}
48504
48505UA_StatusCode
48506UA_Client_HistoryRead_raw(UA_Client *client, const UA_NodeId *nodeId,
48507 const UA_HistoricalIteratorCallback callback,
48508 UA_DateTime startTime, UA_DateTime endTime,
48509 UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode,
48510 UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
48511
48512 return __UA_Client_HistoryRead_service_rawMod(client, nodeId, callback, startTime, endTime, indexRange, returnBounds,
48513 numValuesPerNode, false, timestampsToReturn, callbackContext);
48514}
48515
48516#ifdef UA_ENABLE_EXPERIMENTAL_HISTORIZING
48517UA_StatusCode
48518UA_Client_HistoryRead_modified(UA_Client *client, const UA_NodeId *nodeId,
48519 const UA_HistoricalIteratorCallback callback,
48520 UA_DateTime startTime, UA_DateTime endTime,
48521 UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 maxItems,
48522 UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
48523
48524 return __UA_Client_HistoryRead_service_rawMod(client, nodeId, callback, startTime, endTime, indexRange, returnBounds,
48525 numValuesPerNode: maxItems, true, timestampsToReturn, callbackContext);
48526}
48527#endif // UA_ENABLE_EXPERIMENTAL_HISTORIZING
48528
48529static UA_HistoryUpdateResponse
48530__UA_Client_HistoryUpdate(UA_Client *client,
48531 void *details,
48532 size_t typeId)
48533{
48534 UA_HistoryUpdateRequest request;
48535 UA_HistoryUpdateRequest_init(p: &request);
48536
48537 UA_ExtensionObject extension;
48538 UA_ExtensionObject_init(p: &extension);
48539 request.historyUpdateDetailsSize = 1;
48540 request.historyUpdateDetails = &extension;
48541
48542 extension.encoding = UA_EXTENSIONOBJECT_DECODED;
48543 extension.content.decoded.type = &UA_TYPES[typeId];
48544 extension.content.decoded.data = details;
48545
48546 UA_HistoryUpdateResponse response;
48547 response = UA_Client_Service_historyUpdate(client, request);
48548 return response;
48549}
48550
48551static UA_StatusCode
48552__UA_Client_HistoryUpdate_updateData(UA_Client *client,
48553 const UA_NodeId *nodeId,
48554 UA_PerformUpdateType type,
48555 UA_DataValue *value)
48556{
48557 UA_StatusCode ret = UA_STATUSCODE_GOOD;
48558 UA_UpdateDataDetails details;
48559 UA_UpdateDataDetails_init(p: &details);
48560
48561 details.performInsertReplace = type;
48562 details.updateValuesSize = 1;
48563 details.updateValues = value;
48564 UA_NodeId_copy(src: nodeId, dst: &details.nodeId);
48565
48566 UA_HistoryUpdateResponse response;
48567 response = __UA_Client_HistoryUpdate(client, details: &details, UA_TYPES_UPDATEDATADETAILS);
48568 if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
48569 ret = response.responseHeader.serviceResult;
48570 goto cleanup;
48571 }
48572 if (response.resultsSize != 1 || response.results[0].operationResultsSize != 1) {
48573 ret = UA_STATUSCODE_BADUNEXPECTEDERROR;
48574 goto cleanup;
48575 }
48576 if (response.results[0].statusCode != UA_STATUSCODE_GOOD) {
48577 ret = response.results[0].statusCode;
48578 goto cleanup;
48579 }
48580 ret = response.results[0].operationResults[0];
48581cleanup:
48582 UA_HistoryUpdateResponse_clear(p: &response);
48583 UA_NodeId_clear(p: &details.nodeId);
48584 return ret;
48585}
48586
48587UA_StatusCode
48588UA_Client_HistoryUpdate_insert(UA_Client *client,
48589 const UA_NodeId *nodeId,
48590 UA_DataValue *value)
48591{
48592 return __UA_Client_HistoryUpdate_updateData(client,
48593 nodeId,
48594 type: UA_PERFORMUPDATETYPE_INSERT,
48595 value);
48596}
48597
48598UA_StatusCode
48599UA_Client_HistoryUpdate_replace(UA_Client *client,
48600 const UA_NodeId *nodeId,
48601 UA_DataValue *value)
48602{
48603 return __UA_Client_HistoryUpdate_updateData(client,
48604 nodeId,
48605 type: UA_PERFORMUPDATETYPE_REPLACE,
48606 value);
48607}
48608
48609UA_StatusCode
48610UA_Client_HistoryUpdate_update(UA_Client *client,
48611 const UA_NodeId *nodeId,
48612 UA_DataValue *value)
48613{
48614 return __UA_Client_HistoryUpdate_updateData(client,
48615 nodeId,
48616 type: UA_PERFORMUPDATETYPE_UPDATE,
48617 value);
48618}
48619
48620UA_StatusCode
48621UA_Client_HistoryUpdate_deleteRaw(UA_Client *client,
48622 const UA_NodeId *nodeId,
48623 UA_DateTime startTimestamp,
48624 UA_DateTime endTimestamp)
48625{
48626 UA_StatusCode ret = UA_STATUSCODE_GOOD;
48627
48628 UA_DeleteRawModifiedDetails details;
48629 UA_DeleteRawModifiedDetails_init(p: &details);
48630
48631 details.isDeleteModified = false;
48632 details.startTime = startTimestamp;
48633 details.endTime = endTimestamp;
48634 UA_NodeId_copy(src: nodeId, dst: &details.nodeId);
48635
48636 UA_HistoryUpdateResponse response;
48637 response = __UA_Client_HistoryUpdate(client, details: &details, UA_TYPES_DELETERAWMODIFIEDDETAILS);
48638 if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
48639 ret = response.responseHeader.serviceResult;
48640 goto cleanup;
48641 }
48642 if (response.resultsSize != 1) {
48643 ret = UA_STATUSCODE_BADUNEXPECTEDERROR;
48644 goto cleanup;
48645 }
48646
48647 ret = response.results[0].statusCode;
48648
48649cleanup:
48650 UA_HistoryUpdateResponse_clear(p: &response);
48651 UA_NodeId_clear(p: &details.nodeId);
48652 return ret;
48653}
48654#endif // UA_ENABLE_HISTORIZING
48655
48656/*******************/
48657/* Async Functions */
48658/*******************/
48659
48660/*Write Attributes*/
48661UA_StatusCode __UA_Client_writeAttribute_async(UA_Client *client,
48662 const UA_NodeId *nodeId, UA_AttributeId attributeId, const void *in,
48663 const UA_DataType *inDataType, UA_ClientAsyncServiceCallback callback,
48664 void *userdata, UA_UInt32 *reqId) {
48665 if (!in)
48666 return UA_STATUSCODE_BADTYPEMISMATCH;
48667
48668 UA_WriteValue wValue;
48669 UA_WriteValue_init(p: &wValue);
48670 wValue.nodeId = *nodeId;
48671 wValue.attributeId = attributeId;
48672 if (attributeId == UA_ATTRIBUTEID_VALUE)
48673 wValue.value.value = *(const UA_Variant*) in;
48674 else
48675 /* hack. is never written into. */
48676 UA_Variant_setScalar(v: &wValue.value.value, p: (void*) (uintptr_t) in,
48677 type: inDataType);
48678 wValue.value.hasValue = true;
48679 UA_WriteRequest wReq;
48680 UA_WriteRequest_init(p: &wReq);
48681 wReq.nodesToWrite = &wValue;
48682 wReq.nodesToWriteSize = 1;
48683
48684 return __UA_Client_AsyncService(client, request: &wReq,
48685 requestType: &UA_TYPES[UA_TYPES_WRITEREQUEST], callback,
48686 responseType: &UA_TYPES[UA_TYPES_WRITERESPONSE], userdata, requestId: reqId);
48687}
48688
48689/*Node Management*/
48690
48691UA_StatusCode UA_EXPORT
48692__UA_Client_addNode_async(UA_Client *client, const UA_NodeClass nodeClass,
48693 const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
48694 const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
48695 const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
48696 const UA_DataType *attributeType, UA_NodeId *outNewNodeId,
48697 UA_ClientAsyncServiceCallback callback, void *userdata,
48698 UA_UInt32 *reqId) {
48699 UA_AddNodesRequest request;
48700 UA_AddNodesRequest_init(p: &request);
48701 UA_AddNodesItem item;
48702 UA_AddNodesItem_init(p: &item);
48703 item.parentNodeId.nodeId = parentNodeId;
48704 item.referenceTypeId = referenceTypeId;
48705 item.requestedNewNodeId.nodeId = requestedNewNodeId;
48706 item.browseName = browseName;
48707 item.nodeClass = nodeClass;
48708 item.typeDefinition.nodeId = typeDefinition;
48709 item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
48710 item.nodeAttributes.content.decoded.type = attributeType;
48711 item.nodeAttributes.content.decoded.data = (void*) (uintptr_t) attr; // hack. is not written into.
48712 request.nodesToAdd = &item;
48713 request.nodesToAddSize = 1;
48714
48715 return __UA_Client_AsyncService(client, request: &request,
48716 requestType: &UA_TYPES[UA_TYPES_ADDNODESREQUEST], callback,
48717 responseType: &UA_TYPES[UA_TYPES_ADDNODESRESPONSE], userdata, requestId: reqId);
48718
48719}
48720
48721/* Misc Highlevel Functions */
48722#ifdef UA_ENABLE_METHODCALLS
48723UA_StatusCode __UA_Client_call_async(UA_Client *client,
48724 const UA_NodeId objectId, const UA_NodeId methodId, size_t inputSize,
48725 const UA_Variant *input, UA_ClientAsyncServiceCallback callback,
48726 void *userdata, UA_UInt32 *reqId) {
48727
48728 UA_CallRequest request;
48729 UA_CallRequest_init(p: &request);
48730 UA_CallMethodRequest item;
48731 UA_CallMethodRequest_init(p: &item);
48732 item.methodId = methodId;
48733 item.objectId = objectId;
48734 item.inputArguments = (UA_Variant *) (void*) (uintptr_t) input; // cast const...
48735 item.inputArgumentsSize = inputSize;
48736 request.methodsToCall = &item;
48737 request.methodsToCallSize = 1;
48738
48739 return __UA_Client_AsyncService(client, request: &request,
48740 requestType: &UA_TYPES[UA_TYPES_CALLREQUEST], callback,
48741 responseType: &UA_TYPES[UA_TYPES_CALLRESPONSE], userdata, requestId: reqId);
48742}
48743#endif
48744
48745/* UA_StatusCode */
48746/* UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths, */
48747/* UA_UInt32 *ids, size_t pathSize, */
48748/* UA_ClientAsyncTranslateCallback callback, */
48749/* void *userdata, UA_UInt32 *reqId) { */
48750/* return UA_STATUSCODE_BADNOTIMPLEMENTED; */
48751/* } */
48752
48753/*************************/
48754/* Read Single Attribute */
48755/*************************/
48756
48757typedef struct {
48758 UA_ClientAsyncOperationCallback userCallback;
48759 void *userContext;
48760 const UA_DataType *resultType; /* DataValue -> Value attribute,
48761 * Variant -> ArrayDimensions attribute */
48762} UA_AttributeReadContext;
48763
48764static void
48765AttributeReadCallback(UA_Client *client, void *userdata,
48766 UA_UInt32 requestId, UA_ReadResponse *rr) {
48767 UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)userdata;
48768 UA_LOG_DEBUG(logger: &UA_Client_getConfig(client)->logger, category: UA_LOGCATEGORY_CLIENT,
48769 msg: "Async read response for request %" PRIu32, requestId);
48770
48771 UA_DataValue *dv = NULL;
48772
48773 /* Check the ServiceResult */
48774 UA_StatusCode res = rr->responseHeader.serviceResult;
48775 if(res != UA_STATUSCODE_GOOD)
48776 goto finish;
48777
48778 /* Check result array size */
48779 if(rr->resultsSize != 1) {
48780 res = UA_STATUSCODE_BADINTERNALERROR;
48781 goto finish;
48782 }
48783
48784 /* A Value attribute */
48785 dv = &rr->results[0];
48786 if(ctx->resultType == &UA_TYPES[UA_TYPES_DATAVALUE]) {
48787 ctx->userCallback(client, ctx->userContext, requestId,
48788 UA_STATUSCODE_GOOD, dv);
48789 goto finish;
48790 }
48791
48792 /* An ArrayDimensions attribute. Has to be an array of UInt32. */
48793 if(ctx->resultType == &UA_TYPES[UA_TYPES_VARIANT]) {
48794 if(dv->hasValue &&
48795 UA_Variant_hasArrayType(v: &dv->value, type: &UA_TYPES[UA_TYPES_UINT32])) {
48796 ctx->userCallback(client, ctx->userContext, requestId,
48797 UA_STATUSCODE_GOOD, &dv->value);
48798 } else {
48799 res = UA_STATUSCODE_BADINTERNALERROR;
48800 }
48801 goto finish;
48802 }
48803
48804 /* Check we have a scalar value of the right datatype */
48805 if(!dv->hasValue ||
48806 !UA_Variant_hasScalarType(v: &dv->value, type: ctx->resultType)) {
48807 res = UA_STATUSCODE_BADINTERNALERROR;
48808 goto finish;
48809 }
48810
48811 /* Callback into userland */
48812 ctx->userCallback(client, ctx->userContext, requestId,
48813 UA_STATUSCODE_GOOD, dv->value.data);
48814
48815 finish:
48816 if(res != UA_STATUSCODE_GOOD)
48817 ctx->userCallback(client, ctx->userContext, requestId, res, NULL);
48818 UA_free(ptr: ctx);
48819}
48820
48821static UA_StatusCode
48822readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
48823 UA_TimestampsToReturn timestampsToReturn,
48824 const UA_DataType *resultType, /* For the specialized reads */
48825 UA_ClientAsyncOperationCallback callback,
48826 void *userdata, UA_UInt32 *requestId) {
48827 UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)
48828 UA_malloc(size: sizeof(UA_AttributeReadContext));
48829 if(!ctx)
48830 return UA_STATUSCODE_BADOUTOFMEMORY;
48831
48832 ctx->userCallback = callback;
48833 ctx->userContext = userdata;
48834 ctx->resultType = resultType;
48835
48836 UA_ReadRequest request;
48837 UA_ReadRequest_init(p: &request);
48838 request.nodesToRead = (UA_ReadValueId*)(uintptr_t)rvi; /* hack, treated as const */
48839 request.nodesToReadSize = 1;
48840 request.timestampsToReturn = timestampsToReturn;
48841
48842 UA_StatusCode res =
48843 __UA_Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_READREQUEST],
48844 callback: (UA_ClientAsyncServiceCallback)AttributeReadCallback,
48845 responseType: &UA_TYPES[UA_TYPES_READRESPONSE], userdata: ctx, requestId);
48846 if(res != UA_STATUSCODE_GOOD)
48847 UA_free(ptr: ctx);
48848 return res;
48849}
48850
48851UA_StatusCode
48852UA_Client_readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
48853 UA_TimestampsToReturn timestampsToReturn,
48854 UA_ClientAsyncReadAttributeCallback callback,
48855 void *userdata, UA_UInt32 *requestId) {
48856 return readAttribute_async(client, rvi, timestampsToReturn,
48857 resultType: &UA_TYPES[UA_TYPES_DATAVALUE], /* special handling */
48858 callback: (UA_ClientAsyncOperationCallback)callback,
48859 userdata, requestId);
48860}
48861
48862/* Helper to keep the code short */
48863static UA_StatusCode
48864readAttribute_simpleAsync(UA_Client *client, const UA_NodeId *nodeId,
48865 UA_AttributeId attributeId, const UA_DataType *resultType,
48866 UA_ClientAsyncOperationCallback callback,
48867 void *userdata, UA_UInt32 *requestId) {
48868 UA_ReadValueId rvi;
48869 UA_ReadValueId_init(p: &rvi);
48870 rvi.nodeId = *nodeId;
48871 rvi.attributeId = attributeId;
48872 return readAttribute_async(client, rvi: &rvi, timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER,
48873 resultType, callback, userdata, requestId);
48874}
48875
48876UA_StatusCode
48877UA_Client_readValueAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48878 UA_ClientAsyncReadValueAttributeCallback callback,
48879 void *userdata, UA_UInt32 *requestId) {
48880 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_VALUE,
48881 resultType: &UA_TYPES[UA_TYPES_DATAVALUE], /* special hndling */
48882 callback: (UA_ClientAsyncOperationCallback)callback,
48883 userdata, requestId);
48884}
48885
48886UA_StatusCode
48887UA_Client_readDataTypeAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48888 UA_ClientAsyncReadDataTypeAttributeCallback callback,
48889 void *userdata, UA_UInt32 *requestId) {
48890 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DATATYPE,
48891 resultType: &UA_TYPES[UA_TYPES_NODEID],
48892 callback: (UA_ClientAsyncOperationCallback)callback,
48893 userdata, requestId);
48894}
48895
48896UA_StatusCode
48897UA_Client_readArrayDimensionsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48898 UA_ClientReadArrayDimensionsAttributeCallback callback,
48899 void *userdata, UA_UInt32 *requestId) {
48900 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ARRAYDIMENSIONS,
48901 resultType: &UA_TYPES[UA_TYPES_VARIANT], /* special handling */
48902 callback: (UA_ClientAsyncOperationCallback)callback,
48903 userdata, requestId);
48904}
48905
48906UA_StatusCode
48907UA_Client_readNodeClassAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48908 UA_ClientAsyncReadNodeClassAttributeCallback callback,
48909 void *userdata, UA_UInt32 *requestId) {
48910 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_NODECLASS,
48911 resultType: &UA_TYPES[UA_TYPES_NODECLASS],
48912 callback: (UA_ClientAsyncOperationCallback)callback,
48913 userdata, requestId);
48914}
48915
48916UA_StatusCode
48917UA_Client_readBrowseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48918 UA_ClientAsyncReadBrowseNameAttributeCallback callback,
48919 void *userdata, UA_UInt32 *requestId) {
48920 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_BROWSENAME,
48921 resultType: &UA_TYPES[UA_TYPES_QUALIFIEDNAME],
48922 callback: (UA_ClientAsyncOperationCallback)callback,
48923 userdata, requestId);
48924}
48925
48926UA_StatusCode
48927UA_Client_readDisplayNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48928 UA_ClientAsyncReadDisplayNameAttributeCallback callback,
48929 void *userdata, UA_UInt32 *requestId) {
48930 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DISPLAYNAME,
48931 resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
48932 callback: (UA_ClientAsyncOperationCallback)callback,
48933 userdata, requestId);
48934}
48935
48936UA_StatusCode
48937UA_Client_readDescriptionAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48938 UA_ClientAsyncReadDescriptionAttributeCallback callback,
48939 void *userdata, UA_UInt32 *requestId) {
48940 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DESCRIPTION,
48941 resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
48942 callback: (UA_ClientAsyncOperationCallback)callback,
48943 userdata, requestId);
48944}
48945
48946UA_StatusCode
48947UA_Client_readWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48948 UA_ClientAsyncReadWriteMaskAttributeCallback callback,
48949 void *userdata, UA_UInt32 *requestId) {
48950 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_WRITEMASK,
48951 resultType: &UA_TYPES[UA_TYPES_UINT32],
48952 callback: (UA_ClientAsyncOperationCallback)callback,
48953 userdata, requestId);
48954}
48955
48956UA_StatusCode UA_EXPORT
48957UA_Client_readUserWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48958 UA_ClientAsyncReadUserWriteMaskAttributeCallback callback,
48959 void *userdata, UA_UInt32 *requestId) {
48960 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USERWRITEMASK,
48961 resultType: &UA_TYPES[UA_TYPES_UINT32],
48962 callback: (UA_ClientAsyncOperationCallback)callback,
48963 userdata, requestId);
48964}
48965
48966UA_StatusCode
48967UA_Client_readIsAbstractAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48968 UA_ClientAsyncReadIsAbstractAttributeCallback callback,
48969 void *userdata, UA_UInt32 *requestId) {
48970 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ISABSTRACT,
48971 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
48972 callback: (UA_ClientAsyncOperationCallback)callback,
48973 userdata, requestId);
48974}
48975
48976UA_StatusCode
48977UA_Client_readSymmetricAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48978 UA_ClientAsyncReadSymmetricAttributeCallback callback,
48979 void *userdata, UA_UInt32 *requestId) {
48980 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_SYMMETRIC,
48981 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
48982 callback: (UA_ClientAsyncOperationCallback)callback,
48983 userdata, requestId);
48984}
48985
48986UA_StatusCode
48987UA_Client_readInverseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48988 UA_ClientAsyncReadInverseNameAttributeCallback callback,
48989 void *userdata, UA_UInt32 *requestId) {
48990 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_INVERSENAME,
48991 resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
48992 callback: (UA_ClientAsyncOperationCallback)callback,
48993 userdata, requestId);
48994}
48995
48996UA_StatusCode
48997UA_Client_readContainsNoLoopsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
48998 UA_ClientAsyncReadContainsNoLoopsAttributeCallback callback,
48999 void *userdata, UA_UInt32 *requestId) {
49000 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_CONTAINSNOLOOPS,
49001 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49002 callback: (UA_ClientAsyncOperationCallback)callback,
49003 userdata, requestId);
49004}
49005
49006UA_StatusCode
49007UA_Client_readEventNotifierAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49008 UA_ClientAsyncReadEventNotifierAttributeCallback callback,
49009 void *userdata, UA_UInt32 *requestId) {
49010 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_EVENTNOTIFIER,
49011 resultType: &UA_TYPES[UA_TYPES_BYTE],
49012 callback: (UA_ClientAsyncOperationCallback)callback,
49013 userdata, requestId);
49014}
49015
49016UA_StatusCode
49017UA_Client_readValueRankAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49018 UA_ClientAsyncReadValueRankAttributeCallback callback,
49019 void *userdata, UA_UInt32 *requestId) {
49020 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_VALUERANK,
49021 resultType: &UA_TYPES[UA_TYPES_INT32],
49022 callback: (UA_ClientAsyncOperationCallback)callback,
49023 userdata, requestId);
49024}
49025
49026UA_StatusCode
49027UA_Client_readAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49028 UA_ClientAsyncReadAccessLevelAttributeCallback callback,
49029 void *userdata, UA_UInt32 *requestId) {
49030 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ACCESSLEVEL,
49031 resultType: &UA_TYPES[UA_TYPES_BYTE],
49032 callback: (UA_ClientAsyncOperationCallback)callback,
49033 userdata, requestId);
49034}
49035
49036UA_StatusCode
49037UA_Client_readUserAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49038 UA_ClientAsyncReadUserAccessLevelAttributeCallback callback,
49039 void *userdata, UA_UInt32 *requestId) {
49040 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USERACCESSLEVEL,
49041 resultType: &UA_TYPES[UA_TYPES_BYTE],
49042 callback: (UA_ClientAsyncOperationCallback)callback,
49043 userdata, requestId);
49044}
49045
49046UA_StatusCode
49047UA_Client_readMinimumSamplingIntervalAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49048 UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback callback,
49049 void *userdata, UA_UInt32 *requestId) {
49050 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
49051 resultType: &UA_TYPES[UA_TYPES_DOUBLE],
49052 callback: (UA_ClientAsyncOperationCallback)callback,
49053 userdata, requestId);
49054}
49055
49056UA_StatusCode
49057UA_Client_readHistorizingAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49058 UA_ClientAsyncReadHistorizingAttributeCallback callback,
49059 void *userdata, UA_UInt32 *requestId) {
49060 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_HISTORIZING,
49061 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49062 callback: (UA_ClientAsyncOperationCallback)callback,
49063 userdata, requestId);
49064}
49065
49066UA_StatusCode
49067UA_Client_readExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49068 UA_ClientAsyncReadExecutableAttributeCallback callback,
49069 void *userdata, UA_UInt32 *requestId) {
49070 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_EXECUTABLE,
49071 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49072 callback: (UA_ClientAsyncOperationCallback)callback,
49073 userdata, requestId);
49074}
49075
49076UA_StatusCode
49077UA_Client_readUserExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49078 UA_ClientAsyncReadUserExecutableAttributeCallback callback,
49079 void *userdata, UA_UInt32 *requestId) {
49080 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USEREXECUTABLE,
49081 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49082 callback: (UA_ClientAsyncOperationCallback)callback,
49083 userdata, requestId);
49084}
49085
49086/**** amalgamated original file "/src/client/ua_client_subscriptions.c" ****/
49087
49088/* This Source Code Form is subject to the terms of the Mozilla Public
49089 * License, v. 2.0. If a copy of the MPL was not distributed with this
49090 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
49091 *
49092 * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
49093 * Copyright 2015 (c) Oleksiy Vasylyev
49094 * Copyright 2016 (c) Sten Grüner
49095 * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
49096 * Copyright 2016-2017 (c) Florian Palm
49097 * Copyright 2017 (c) Frank Meerkötter
49098 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
49099 */
49100
49101
49102
49103#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
49104
49105/*****************/
49106/* Subscriptions */
49107/*****************/
49108
49109static void
49110MonitoredItem_delete(UA_Client *client, UA_Client_Subscription *sub,
49111 UA_Client_MonitoredItem *mon);
49112
49113static void
49114ua_Subscriptions_create(UA_Client *client, UA_Client_Subscription *newSub,
49115 UA_CreateSubscriptionResponse *response) {
49116 newSub->subscriptionId = response->subscriptionId;
49117 newSub->sequenceNumber = 0;
49118 newSub->lastActivity = UA_DateTime_nowMonotonic();
49119 newSub->publishingInterval = response->revisedPublishingInterval;
49120 newSub->maxKeepAliveCount = response->revisedMaxKeepAliveCount;
49121 LIST_INIT(&newSub->monitoredItems);
49122 LIST_INSERT_HEAD(&client->subscriptions, newSub, listEntry);
49123}
49124
49125static void
49126ua_Subscriptions_create_handler(UA_Client *client, void *data, UA_UInt32 requestId,
49127 void *r) {
49128 UA_CreateSubscriptionResponse *response = (UA_CreateSubscriptionResponse *)r;
49129 CustomCallback *cc = (CustomCallback *)data;
49130 UA_Client_Subscription *newSub = (UA_Client_Subscription *)cc->clientData;
49131 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
49132 UA_free(ptr: newSub);
49133 goto cleanup;
49134 }
49135
49136 /* Prepare the internal representation */
49137 ua_Subscriptions_create(client, newSub, response);
49138
49139cleanup:
49140 if(cc->userCallback)
49141 cc->userCallback(client, cc->userData, requestId, response);
49142 UA_free(ptr: cc);
49143}
49144
49145UA_CreateSubscriptionResponse
49146UA_Client_Subscriptions_create(UA_Client *client,
49147 const UA_CreateSubscriptionRequest request,
49148 void *subscriptionContext,
49149 UA_Client_StatusChangeNotificationCallback statusChangeCallback,
49150 UA_Client_DeleteSubscriptionCallback deleteCallback) {
49151 UA_CreateSubscriptionResponse response;
49152 UA_Client_Subscription *sub = (UA_Client_Subscription *)
49153 UA_malloc(size: sizeof(UA_Client_Subscription));
49154 if(!sub) {
49155 UA_CreateSubscriptionResponse_init(p: &response);
49156 response.responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
49157 return response;
49158 }
49159 sub->context = subscriptionContext;
49160 sub->statusChangeCallback = statusChangeCallback;
49161 sub->deleteCallback = deleteCallback;
49162
49163 /* Send the request as a synchronous service call */
49164 __UA_Client_Service(client,
49165 request: &request, requestType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
49166 response: &response, responseType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
49167 if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49168 {
49169 UA_free (ptr: sub);
49170 return response;
49171 }
49172
49173 ua_Subscriptions_create(client, newSub: sub, response: &response);
49174 return response;
49175}
49176
49177UA_StatusCode
49178UA_Client_Subscriptions_create_async(UA_Client *client,
49179 const UA_CreateSubscriptionRequest request,
49180 void *subscriptionContext,
49181 UA_Client_StatusChangeNotificationCallback statusChangeCallback,
49182 UA_Client_DeleteSubscriptionCallback deleteCallback,
49183 UA_ClientAsyncServiceCallback createCallback,
49184 void *userdata,
49185 UA_UInt32 *requestId) {
49186 CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback));
49187 if(!cc)
49188 return UA_STATUSCODE_BADOUTOFMEMORY;
49189
49190 UA_Client_Subscription *sub = (UA_Client_Subscription *)
49191 UA_malloc(size: sizeof(UA_Client_Subscription));
49192 if(!sub) {
49193 UA_free(ptr: cc);
49194 return UA_STATUSCODE_BADOUTOFMEMORY;
49195 }
49196 sub->context = subscriptionContext;
49197 sub->statusChangeCallback = statusChangeCallback;
49198 sub->deleteCallback = deleteCallback;
49199
49200 cc->userCallback = createCallback;
49201 cc->userData = userdata;
49202 cc->clientData = sub;
49203
49204 /* Send the request as asynchronous service call */
49205 return __UA_Client_AsyncService(
49206 client, request: &request, requestType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
49207 callback: ua_Subscriptions_create_handler, responseType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE],
49208 userdata: cc, requestId);
49209}
49210
49211static UA_Client_Subscription *
49212findSubscription(const UA_Client *client, UA_UInt32 subscriptionId) {
49213 UA_Client_Subscription *sub = NULL;
49214 LIST_FOREACH(sub, &client->subscriptions, listEntry) {
49215 if(sub->subscriptionId == subscriptionId)
49216 break;
49217 }
49218 return sub;
49219}
49220
49221static void
49222ua_Subscriptions_modify(UA_Client *client, UA_Client_Subscription *sub,
49223 const UA_ModifySubscriptionResponse *response) {
49224 sub->publishingInterval = response->revisedPublishingInterval;
49225 sub->maxKeepAliveCount = response->revisedMaxKeepAliveCount;
49226}
49227
49228static void
49229ua_Subscriptions_modify_handler(UA_Client *client, void *data, UA_UInt32 requestId,
49230 void *r) {
49231 UA_ModifySubscriptionResponse *response = (UA_ModifySubscriptionResponse *)r;
49232 CustomCallback *cc = (CustomCallback *)data;
49233 UA_Client_Subscription *sub =
49234 findSubscription(client, subscriptionId: (UA_UInt32)(uintptr_t)cc->clientData);
49235 if(sub) {
49236 ua_Subscriptions_modify(client, sub, response);
49237 } else {
49238 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49239 msg: "No internal representation of subscription %" PRIu32,
49240 (UA_UInt32)(uintptr_t)cc->clientData);
49241 }
49242
49243 if(cc->userCallback)
49244 cc->userCallback(client, cc->userData, requestId, response);
49245 UA_free(ptr: cc);
49246}
49247
49248UA_ModifySubscriptionResponse
49249UA_Client_Subscriptions_modify(UA_Client *client,
49250 const UA_ModifySubscriptionRequest request) {
49251 UA_ModifySubscriptionResponse response;
49252 UA_ModifySubscriptionResponse_init(p: &response);
49253
49254 /* Find the internal representation */
49255 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId);
49256 if(!sub) {
49257 response.responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49258 return response;
49259 }
49260
49261 /* Call the service */
49262 __UA_Client_Service(client,
49263 request: &request, requestType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
49264 response: &response, responseType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
49265
49266 /* Adjust the internal representation */
49267 ua_Subscriptions_modify(client, sub, response: &response);
49268 return response;
49269}
49270
49271UA_StatusCode
49272UA_Client_Subscriptions_modify_async(UA_Client *client,
49273 const UA_ModifySubscriptionRequest request,
49274 UA_ClientAsyncServiceCallback callback,
49275 void *userdata, UA_UInt32 *requestId) {
49276 /* Find the internal representation */
49277 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId);
49278 if(!sub)
49279 return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49280
49281 CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback));
49282 if(!cc)
49283 return UA_STATUSCODE_BADOUTOFMEMORY;
49284
49285 cc->clientData = (void *)(uintptr_t)request.subscriptionId;
49286 cc->userData = userdata;
49287 cc->userCallback = callback;
49288
49289 return __UA_Client_AsyncService(
49290 client, request: &request, requestType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
49291 callback: ua_Subscriptions_modify_handler, responseType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE],
49292 userdata: cc, requestId);
49293}
49294
49295static void
49296UA_Client_Subscription_deleteInternal(UA_Client *client,
49297 UA_Client_Subscription *sub) {
49298 /* Remove the MonitoredItems */
49299 UA_Client_MonitoredItem *mon;
49300 UA_Client_MonitoredItem *mon_tmp;
49301 LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, mon_tmp)
49302 MonitoredItem_delete(client, sub, mon);
49303
49304 /* Call the delete callback */
49305 if(sub->deleteCallback)
49306 sub->deleteCallback(client, sub->subscriptionId, sub->context);
49307
49308 /* Remove */
49309 LIST_REMOVE(sub, listEntry);
49310 UA_free(ptr: sub);
49311}
49312
49313static void
49314UA_Client_Subscription_processDelete(UA_Client *client,
49315 const UA_DeleteSubscriptionsRequest *request,
49316 const UA_DeleteSubscriptionsResponse *response) {
49317 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49318 return;
49319
49320 /* Check that the request and response size -- use the same index for both */
49321 if(request->subscriptionIdsSize != response->resultsSize)
49322 return;
49323
49324 for(size_t i = 0; i < request->subscriptionIdsSize; i++) {
49325 if(response->results[i] != UA_STATUSCODE_GOOD &&
49326 response->results[i] != UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID)
49327 continue;
49328
49329 /* Get the Subscription */
49330 UA_Client_Subscription *sub =
49331 findSubscription(client, subscriptionId: request->subscriptionIds[i]);
49332 if(!sub) {
49333 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49334 msg: "No internal representation of subscription %" PRIu32,
49335 request->subscriptionIds[i]);
49336 continue;
49337 }
49338
49339 /* Delete the Subscription */
49340 UA_Client_Subscription_deleteInternal(client, sub);
49341 }
49342
49343}
49344
49345typedef struct {
49346 UA_DeleteSubscriptionsRequest request;
49347 UA_ClientAsyncServiceCallback userCallback;
49348 void *userData;
49349} DeleteSubscriptionCallback;
49350
49351static void
49352ua_Subscriptions_delete_handler(UA_Client *client, void *data, UA_UInt32 requestId,
49353 void *r) {
49354 UA_DeleteSubscriptionsResponse *response =
49355 (UA_DeleteSubscriptionsResponse *)r;
49356 DeleteSubscriptionCallback *dsc =
49357 (DeleteSubscriptionCallback*)data;
49358
49359 /* Delete */
49360 UA_Client_Subscription_processDelete(client, request: &dsc->request, response);
49361
49362 /* Userland Callback */
49363 dsc->userCallback(client, dsc->userData, requestId, response);
49364
49365 /* Cleanup */
49366 UA_DeleteSubscriptionsRequest_clear(p: &dsc->request);
49367 UA_free(ptr: dsc);
49368}
49369
49370UA_StatusCode
49371UA_Client_Subscriptions_delete_async(UA_Client *client,
49372 const UA_DeleteSubscriptionsRequest request,
49373 UA_ClientAsyncServiceCallback callback,
49374 void *userdata, UA_UInt32 *requestId) {
49375 /* Make a copy of the request that persists into the async callback */
49376 DeleteSubscriptionCallback *dsc =
49377 (DeleteSubscriptionCallback*)UA_malloc(size: sizeof(DeleteSubscriptionCallback));
49378 if(!dsc)
49379 return UA_STATUSCODE_BADOUTOFMEMORY;
49380 dsc->userCallback = callback;
49381 dsc->userData = userdata;
49382 UA_StatusCode res = UA_DeleteSubscriptionsRequest_copy(src: &request, dst: &dsc->request);
49383 if(res != UA_STATUSCODE_GOOD) {
49384 UA_free(ptr: dsc);
49385 return res;
49386 }
49387
49388 /* Make the async call */
49389 return __UA_Client_AsyncService(
49390 client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
49391 callback: ua_Subscriptions_delete_handler, responseType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE],
49392 userdata: dsc, requestId);
49393}
49394
49395UA_DeleteSubscriptionsResponse
49396UA_Client_Subscriptions_delete(UA_Client *client,
49397 const UA_DeleteSubscriptionsRequest request) {
49398 /* Send the request */
49399 UA_DeleteSubscriptionsResponse response;
49400 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
49401 response: &response, responseType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
49402
49403 /* Process */
49404 UA_Client_Subscription_processDelete(client, request: &request, response: &response);
49405 return response;
49406}
49407
49408UA_StatusCode
49409UA_Client_Subscriptions_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId) {
49410 UA_DeleteSubscriptionsRequest request;
49411 UA_DeleteSubscriptionsRequest_init(p: &request);
49412 request.subscriptionIds = &subscriptionId;
49413 request.subscriptionIdsSize = 1;
49414
49415 UA_DeleteSubscriptionsResponse response =
49416 UA_Client_Subscriptions_delete(client, request);
49417
49418 UA_StatusCode retval = response.responseHeader.serviceResult;
49419 if(retval != UA_STATUSCODE_GOOD) {
49420 UA_DeleteSubscriptionsResponse_clear(p: &response);
49421 return retval;
49422 }
49423
49424 if(response.resultsSize != 1) {
49425 UA_DeleteSubscriptionsResponse_clear(p: &response);
49426 return UA_STATUSCODE_BADINTERNALERROR;
49427 }
49428
49429 retval = response.results[0];
49430 UA_DeleteSubscriptionsResponse_clear(p: &response);
49431 return retval;
49432}
49433
49434/******************/
49435/* MonitoredItems */
49436/******************/
49437
49438static void
49439MonitoredItem_delete(UA_Client *client, UA_Client_Subscription *sub,
49440 UA_Client_MonitoredItem *mon) {
49441 LIST_REMOVE(mon, listEntry);
49442 if(mon->deleteCallback)
49443 mon->deleteCallback(client, sub->subscriptionId, sub->context,
49444 mon->monitoredItemId, mon->context);
49445 UA_free(ptr: mon);
49446}
49447
49448typedef struct {
49449 void **contexts;
49450 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks;
49451 void **handlingCallbacks;
49452 UA_CreateMonitoredItemsRequest request;
49453
49454 /* Notify the user that the async callback was processed */
49455 UA_ClientAsyncServiceCallback userCallback;
49456 void *userData;
49457} MonitoredItems_CreateData;
49458
49459static void
49460MonitoredItems_CreateData_clear(UA_Client *client, MonitoredItems_CreateData *data) {
49461 UA_free(ptr: data->contexts);
49462 UA_free(ptr: data->deleteCallbacks);
49463 UA_free(ptr: data->handlingCallbacks);
49464 UA_CreateMonitoredItemsRequest_clear(p: &data->request);
49465}
49466
49467static void
49468ua_MonitoredItems_create(UA_Client *client, MonitoredItems_CreateData *data,
49469 UA_CreateMonitoredItemsResponse *response) {
49470 UA_CreateMonitoredItemsRequest *request = &data->request;
49471 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks = data->deleteCallbacks;
49472
49473 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: data->request.subscriptionId);
49474 if(!sub)
49475 goto cleanup;
49476
49477 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49478 goto cleanup;
49479
49480 if(response->resultsSize != request->itemsToCreateSize) {
49481 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
49482 goto cleanup;
49483 }
49484
49485 /* Add internally */
49486 for(size_t i = 0; i < request->itemsToCreateSize; i++) {
49487 if(response->results[i].statusCode != UA_STATUSCODE_GOOD) {
49488 if(deleteCallbacks[i])
49489 deleteCallbacks[i](client, sub->subscriptionId, sub->context,
49490 0, data->contexts[i]);
49491 continue;
49492 }
49493
49494 UA_Client_MonitoredItem *newMon = (UA_Client_MonitoredItem *)
49495 UA_malloc(size: sizeof(UA_Client_MonitoredItem));
49496 if(!newMon) {
49497 if(deleteCallbacks[i])
49498 deleteCallbacks[i](client, sub->subscriptionId, sub->context, 0,
49499 data->contexts[i]);
49500 continue;
49501 }
49502
49503 newMon->monitoredItemId = response->results[i].monitoredItemId;
49504 newMon->clientHandle = request->itemsToCreate[i].requestedParameters.clientHandle;
49505 newMon->context = data->contexts[i];
49506 newMon->deleteCallback = deleteCallbacks[i];
49507 newMon->handler.dataChangeCallback =
49508 (UA_Client_DataChangeNotificationCallback)(uintptr_t)
49509 data->handlingCallbacks[i];
49510 newMon->isEventMonitoredItem =
49511 (request->itemsToCreate[i].itemToMonitor.attributeId ==
49512 UA_ATTRIBUTEID_EVENTNOTIFIER);
49513 LIST_INSERT_HEAD(&sub->monitoredItems, newMon, listEntry);
49514
49515 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49516 msg: "Subscription %" PRIu32
49517 " | Added a MonitoredItem with handle %" PRIu32,
49518 sub->subscriptionId, newMon->clientHandle);
49519 }
49520 return;
49521
49522 /* Adding failed */
49523 cleanup:
49524 for(size_t i = 0; i < request->itemsToCreateSize; i++) {
49525 if(deleteCallbacks[i])
49526 deleteCallbacks[i](client, data->request.subscriptionId,
49527 sub ? sub->context : NULL, 0, data->contexts[i]);
49528 }
49529}
49530
49531static void
49532ua_MonitoredItems_create_async_handler(UA_Client *client, void *d, UA_UInt32 requestId,
49533 void *r) {
49534 UA_CreateMonitoredItemsResponse *response = (UA_CreateMonitoredItemsResponse *)r;
49535 MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)d;
49536
49537 ua_MonitoredItems_create(client, data, response);
49538
49539 if(data->userCallback)
49540 data->userCallback(client, data->userData, requestId, response);
49541
49542 MonitoredItems_CreateData_clear(client, data);
49543 UA_free(ptr: data);
49544}
49545
49546static UA_StatusCode
49547MonitoredItems_CreateData_prepare(UA_Client *client,
49548 const UA_CreateMonitoredItemsRequest *request,
49549 void **contexts, void **handlingCallbacks,
49550 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49551 MonitoredItems_CreateData *data) {
49552 /* Align arrays and copy over */
49553 UA_StatusCode retval = UA_STATUSCODE_BADOUTOFMEMORY;
49554 data->contexts = (void **)UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(void *));
49555 if(!data->contexts)
49556 goto cleanup;
49557 if(contexts)
49558 memcpy(dest: data->contexts, src: contexts, n: request->itemsToCreateSize * sizeof(void *));
49559
49560 data->deleteCallbacks = (UA_Client_DeleteMonitoredItemCallback *)
49561 UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(UA_Client_DeleteMonitoredItemCallback));
49562 if(!data->deleteCallbacks)
49563 goto cleanup;
49564 if(deleteCallbacks)
49565 memcpy(dest: data->deleteCallbacks, src: deleteCallbacks,
49566 n: request->itemsToCreateSize * sizeof(UA_Client_DeleteMonitoredItemCallback));
49567
49568 data->handlingCallbacks = (void **)
49569 UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(void *));
49570 if(!data->handlingCallbacks)
49571 goto cleanup;
49572 if(handlingCallbacks)
49573 memcpy(dest: data->handlingCallbacks, src: handlingCallbacks,
49574 n: request->itemsToCreateSize * sizeof(void *));
49575
49576 retval = UA_CreateMonitoredItemsRequest_copy(src: request, dst: &data->request);
49577 if(retval != UA_STATUSCODE_GOOD)
49578 goto cleanup;
49579
49580 /* Set the clientHandle */
49581 for(size_t i = 0; i < data->request.itemsToCreateSize; i++)
49582 data->request.itemsToCreate[i].requestedParameters.clientHandle =
49583 ++client->monitoredItemHandles;
49584
49585 return UA_STATUSCODE_GOOD;
49586
49587cleanup:
49588 MonitoredItems_CreateData_clear(client, data);
49589 return retval;
49590}
49591
49592static void
49593ua_Client_MonitoredItems_create(UA_Client *client,
49594 const UA_CreateMonitoredItemsRequest *request,
49595 void **contexts, void **handlingCallbacks,
49596 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49597 UA_CreateMonitoredItemsResponse *response) {
49598 UA_CreateMonitoredItemsResponse_init(p: response);
49599
49600 if(!request->itemsToCreateSize) {
49601 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
49602 return;
49603 }
49604
49605 /* Test if the subscription is valid */
49606 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request->subscriptionId);
49607 if(!sub) {
49608 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49609 return;
49610 }
49611
49612 MonitoredItems_CreateData data;
49613 memset(s: &data, c: 0, n: sizeof(MonitoredItems_CreateData));
49614
49615 UA_StatusCode res =
49616 MonitoredItems_CreateData_prepare(client, request, contexts, handlingCallbacks,
49617 deleteCallbacks, data: &data);
49618 if(res != UA_STATUSCODE_GOOD) {
49619 response->responseHeader.serviceResult = res;
49620 return;
49621 }
49622
49623 /* Call the service. Use data->request as it contains the client handle
49624 * information. */
49625 __UA_Client_Service(client, request: &data.request,
49626 requestType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
49627 response, responseType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
49628
49629 /* Add internal representation */
49630 ua_MonitoredItems_create(client, data: &data, response);
49631
49632 MonitoredItems_CreateData_clear(client, data: &data);
49633}
49634
49635static UA_StatusCode
49636ua_Client_MonitoredItems_createDataChanges_async(
49637 UA_Client *client, const UA_CreateMonitoredItemsRequest request, void **contexts,
49638 void **callbacks, UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49639 UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId) {
49640 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId);
49641 if(!sub)
49642 return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49643
49644 MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)
49645 UA_calloc(nmemb: 1, size: sizeof(MonitoredItems_CreateData));
49646 if(!data)
49647 return UA_STATUSCODE_BADOUTOFMEMORY;
49648 data->userCallback = createCallback;
49649 data->userData = userdata;
49650
49651 UA_StatusCode res = MonitoredItems_CreateData_prepare(
49652 client, request: &request, contexts, handlingCallbacks: callbacks, deleteCallbacks, data);
49653 if(res != UA_STATUSCODE_GOOD) {
49654 UA_free(ptr: data);
49655 return res;
49656 }
49657
49658 return __UA_Client_AsyncService(
49659 client, request: &data->request, requestType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
49660 callback: ua_MonitoredItems_create_async_handler,
49661 responseType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE], userdata: data, requestId);
49662}
49663
49664UA_CreateMonitoredItemsResponse
49665UA_Client_MonitoredItems_createDataChanges(UA_Client *client,
49666 const UA_CreateMonitoredItemsRequest request,
49667 void **contexts,
49668 UA_Client_DataChangeNotificationCallback *callbacks,
49669 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks) {
49670 UA_CreateMonitoredItemsResponse response;
49671 ua_Client_MonitoredItems_create(client, request: &request, contexts, handlingCallbacks: (void **)callbacks,
49672 deleteCallbacks, response: &response);
49673 return response;
49674}
49675
49676UA_StatusCode
49677UA_Client_MonitoredItems_createDataChanges_async(UA_Client *client,
49678 const UA_CreateMonitoredItemsRequest request,
49679 void **contexts,
49680 UA_Client_DataChangeNotificationCallback *callbacks,
49681 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49682 UA_ClientAsyncServiceCallback createCallback,
49683 void *userdata, UA_UInt32 *requestId) {
49684 return ua_Client_MonitoredItems_createDataChanges_async(
49685 client, request, contexts, callbacks: (void **)callbacks, deleteCallbacks, createCallback,
49686 userdata, requestId);
49687}
49688
49689UA_MonitoredItemCreateResult
49690UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscriptionId,
49691 UA_TimestampsToReturn timestampsToReturn,
49692 const UA_MonitoredItemCreateRequest item,
49693 void *context,
49694 UA_Client_DataChangeNotificationCallback callback,
49695 UA_Client_DeleteMonitoredItemCallback deleteCallback) {
49696 UA_CreateMonitoredItemsRequest request;
49697 UA_CreateMonitoredItemsRequest_init(p: &request);
49698 request.subscriptionId = subscriptionId;
49699 request.timestampsToReturn = timestampsToReturn;
49700 request.itemsToCreate = (UA_MonitoredItemCreateRequest*)(uintptr_t)&item;
49701 request.itemsToCreateSize = 1;
49702 UA_CreateMonitoredItemsResponse response =
49703 UA_Client_MonitoredItems_createDataChanges(client, request, contexts: &context,
49704 callbacks: &callback, deleteCallbacks: &deleteCallback);
49705 UA_MonitoredItemCreateResult result;
49706 UA_MonitoredItemCreateResult_init(p: &result);
49707 if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49708 result.statusCode = response.responseHeader.serviceResult;
49709
49710 if(result.statusCode == UA_STATUSCODE_GOOD &&
49711 response.resultsSize != 1)
49712 result.statusCode = UA_STATUSCODE_BADINTERNALERROR;
49713
49714 if(result.statusCode == UA_STATUSCODE_GOOD)
49715 UA_MonitoredItemCreateResult_copy(src: &response.results[0] , dst: &result);
49716 UA_CreateMonitoredItemsResponse_clear(p: &response);
49717 return result;
49718}
49719
49720UA_CreateMonitoredItemsResponse
49721UA_Client_MonitoredItems_createEvents(UA_Client *client,
49722 const UA_CreateMonitoredItemsRequest request,
49723 void **contexts,
49724 UA_Client_EventNotificationCallback *callback,
49725 UA_Client_DeleteMonitoredItemCallback *deleteCallback) {
49726 UA_CreateMonitoredItemsResponse response;
49727 ua_Client_MonitoredItems_create(client, request: &request, contexts, handlingCallbacks: (void **)callback,
49728 deleteCallbacks: deleteCallback, response: &response);
49729 return response;
49730}
49731
49732/* Monitor the EventNotifier attribute only */
49733UA_StatusCode
49734UA_Client_MonitoredItems_createEvents_async(UA_Client *client,
49735 const UA_CreateMonitoredItemsRequest request,
49736 void **contexts,
49737 UA_Client_EventNotificationCallback *callbacks,
49738 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49739 UA_ClientAsyncServiceCallback createCallback,
49740 void *userdata, UA_UInt32 *requestId) {
49741 return ua_Client_MonitoredItems_createDataChanges_async(
49742 client, request, contexts, callbacks: (void **)callbacks, deleteCallbacks, createCallback,
49743 userdata, requestId);
49744}
49745
49746UA_MonitoredItemCreateResult
49747UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId,
49748 UA_TimestampsToReturn timestampsToReturn,
49749 const UA_MonitoredItemCreateRequest item, void *context,
49750 UA_Client_EventNotificationCallback callback,
49751 UA_Client_DeleteMonitoredItemCallback deleteCallback) {
49752 UA_CreateMonitoredItemsRequest request;
49753 UA_CreateMonitoredItemsRequest_init(p: &request);
49754 request.subscriptionId = subscriptionId;
49755 request.timestampsToReturn = timestampsToReturn;
49756 request.itemsToCreate = (UA_MonitoredItemCreateRequest*)(uintptr_t)&item;
49757 request.itemsToCreateSize = 1;
49758 UA_CreateMonitoredItemsResponse response =
49759 UA_Client_MonitoredItems_createEvents(client, request, contexts: &context,
49760 callback: &callback, deleteCallback: &deleteCallback);
49761 UA_StatusCode retval = response.responseHeader.serviceResult;
49762 UA_MonitoredItemCreateResult result;
49763 UA_MonitoredItemCreateResult_init(p: &result);
49764 if(retval != UA_STATUSCODE_GOOD) {
49765 UA_CreateMonitoredItemsResponse_clear(p: &response);
49766 result.statusCode = retval;
49767 return result;
49768 }
49769 UA_MonitoredItemCreateResult_copy(src: response.results , dst: &result);
49770 UA_CreateMonitoredItemsResponse_clear(p: &response);
49771 return result;
49772}
49773
49774static void
49775ua_MonitoredItems_delete(UA_Client *client, UA_Client_Subscription *sub,
49776 const UA_DeleteMonitoredItemsRequest *request,
49777 const UA_DeleteMonitoredItemsResponse *response) {
49778#ifdef __clang_analyzer__
49779 return;
49780#endif
49781
49782 /* Loop over deleted MonitoredItems */
49783 for(size_t i = 0; i < response->resultsSize; i++) {
49784 if(response->results[i] != UA_STATUSCODE_GOOD &&
49785 response->results[i] != UA_STATUSCODE_BADMONITOREDITEMIDINVALID) {
49786 continue;
49787 }
49788
49789 /* Delete the internal representation */
49790 UA_Client_MonitoredItem *mon;
49791 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
49792 if(mon->monitoredItemId == request->monitoredItemIds[i]) {
49793 MonitoredItem_delete(client, sub, mon);
49794 break;
49795 }
49796 }
49797 }
49798}
49799
49800static void
49801ua_MonitoredItems_delete_handler(UA_Client *client, void *d, UA_UInt32 requestId,
49802 void *r) {
49803 UA_Client_Subscription *sub = NULL;
49804 CustomCallback *cc = (CustomCallback *)d;
49805 UA_DeleteMonitoredItemsResponse *response = (UA_DeleteMonitoredItemsResponse *)r;
49806 UA_DeleteMonitoredItemsRequest *request =
49807 (UA_DeleteMonitoredItemsRequest *)cc->clientData;
49808 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49809 goto cleanup;
49810
49811 sub = findSubscription(client, subscriptionId: request->subscriptionId);
49812 if(!sub) {
49813 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49814 msg: "No internal representation of subscription %" PRIu32,
49815 request->subscriptionId);
49816 goto cleanup;
49817 }
49818
49819 /* Delete MonitoredItems from the internal representation */
49820 ua_MonitoredItems_delete(client, sub, request, response);
49821
49822cleanup:
49823 if(cc->userCallback)
49824 cc->userCallback(client, cc->userData, requestId, response);
49825 UA_DeleteMonitoredItemsRequest_delete(p: request);
49826 UA_free(ptr: cc);
49827}
49828
49829UA_DeleteMonitoredItemsResponse
49830UA_Client_MonitoredItems_delete(UA_Client *client,
49831 const UA_DeleteMonitoredItemsRequest request) {
49832 /* Send the request */
49833 UA_DeleteMonitoredItemsResponse response;
49834 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
49835 response: &response, responseType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
49836
49837 /* A problem occured remote? */
49838 if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49839 return response;
49840
49841 /* Find the internal subscription representation */
49842 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId);
49843 if(!sub) {
49844 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49845 msg: "No internal representation of subscription %" PRIu32,
49846 request.subscriptionId);
49847 return response;
49848 }
49849
49850 /* Remove MonitoredItems in the internal representation */
49851 ua_MonitoredItems_delete(client, sub, request: &request, response: &response);
49852 return response;
49853}
49854
49855UA_StatusCode
49856UA_Client_MonitoredItems_delete_async(UA_Client *client,
49857 const UA_DeleteMonitoredItemsRequest request,
49858 UA_ClientAsyncServiceCallback callback,
49859 void *userdata, UA_UInt32 *requestId) {
49860 /* Send the request */
49861 CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback));
49862 if(!cc)
49863 return UA_STATUSCODE_BADOUTOFMEMORY;
49864
49865 UA_DeleteMonitoredItemsRequest *req_copy = UA_DeleteMonitoredItemsRequest_new();
49866 if(!req_copy) {
49867 UA_free(ptr: cc);
49868 return UA_STATUSCODE_BADOUTOFMEMORY;
49869 }
49870
49871 UA_DeleteMonitoredItemsRequest_copy(src: &request, dst: req_copy);
49872 cc->clientData = req_copy;
49873 cc->userCallback = callback;
49874 cc->userData = userdata;
49875
49876 return __UA_Client_AsyncService(
49877 client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
49878 callback: ua_MonitoredItems_delete_handler,
49879 responseType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE], userdata: cc, requestId);
49880}
49881
49882UA_StatusCode
49883UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId,
49884 UA_UInt32 monitoredItemId) {
49885 UA_DeleteMonitoredItemsRequest request;
49886 UA_DeleteMonitoredItemsRequest_init(p: &request);
49887 request.subscriptionId = subscriptionId;
49888 request.monitoredItemIds = &monitoredItemId;
49889 request.monitoredItemIdsSize = 1;
49890
49891 UA_DeleteMonitoredItemsResponse response =
49892 UA_Client_MonitoredItems_delete(client, request);
49893
49894 UA_StatusCode retval = response.responseHeader.serviceResult;
49895 if(retval != UA_STATUSCODE_GOOD) {
49896 UA_DeleteMonitoredItemsResponse_clear(p: &response);
49897 return retval;
49898 }
49899
49900 if(response.resultsSize != 1) {
49901 UA_DeleteMonitoredItemsResponse_clear(p: &response);
49902 return UA_STATUSCODE_BADINTERNALERROR;
49903 }
49904
49905 retval = response.results[0];
49906 UA_DeleteMonitoredItemsResponse_clear(p: &response);
49907 return retval;
49908}
49909
49910UA_ModifyMonitoredItemsResponse
49911UA_Client_MonitoredItems_modify(UA_Client *client,
49912 const UA_ModifyMonitoredItemsRequest request) {
49913 UA_ModifyMonitoredItemsResponse response;
49914
49915 UA_Client_Subscription *sub;
49916 LIST_FOREACH(sub, &client->subscriptions, listEntry) {
49917 if (sub->subscriptionId == request.subscriptionId)
49918 break;
49919 }
49920
49921 if (!sub) {
49922 UA_ModifyMonitoredItemsResponse_init(p: &response);
49923 response.responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49924 return response;
49925 }
49926
49927 UA_ModifyMonitoredItemsRequest modifiedRequest;
49928 UA_ModifyMonitoredItemsRequest_copy(src: &request, dst: &modifiedRequest);
49929
49930 for (size_t i = 0; i < modifiedRequest.itemsToModifySize; ++i) {
49931 UA_Client_MonitoredItem *mon;
49932 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
49933 if(mon->monitoredItemId == modifiedRequest.itemsToModify[i].monitoredItemId) {
49934 modifiedRequest.itemsToModify[i].requestedParameters.clientHandle = mon->clientHandle;
49935 break;
49936 }
49937 }
49938 }
49939
49940 __UA_Client_Service(client,
49941 request: &modifiedRequest, requestType: &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST],
49942 response: &response, responseType: &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]);
49943
49944 UA_ModifyMonitoredItemsRequest_clear(p: &modifiedRequest);
49945 return response;
49946}
49947
49948/*************************************/
49949/* Async Processing of Notifications */
49950/*************************************/
49951
49952/* Assume the request is already initialized */
49953UA_StatusCode
49954UA_Client_preparePublishRequest(UA_Client *client, UA_PublishRequest *request) {
49955 /* Count acks */
49956 UA_Client_NotificationsAckNumber *ack;
49957 LIST_FOREACH(ack, &client->pendingNotificationsAcks, listEntry)
49958 ++request->subscriptionAcknowledgementsSize;
49959
49960 /* Create the array. Returns a sentinel pointer if the length is zero. */
49961 request->subscriptionAcknowledgements = (UA_SubscriptionAcknowledgement*)
49962 UA_Array_new(size: request->subscriptionAcknowledgementsSize,
49963 type: &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT]);
49964 if(!request->subscriptionAcknowledgements) {
49965 request->subscriptionAcknowledgementsSize = 0;
49966 return UA_STATUSCODE_BADOUTOFMEMORY;
49967 }
49968
49969 size_t i = 0;
49970 UA_Client_NotificationsAckNumber *ack_tmp;
49971 LIST_FOREACH_SAFE(ack, &client->pendingNotificationsAcks, listEntry, ack_tmp) {
49972 request->subscriptionAcknowledgements[i].sequenceNumber = ack->subAck.sequenceNumber;
49973 request->subscriptionAcknowledgements[i].subscriptionId = ack->subAck.subscriptionId;
49974 ++i;
49975 LIST_REMOVE(ack, listEntry);
49976 UA_free(ptr: ack);
49977 }
49978 return UA_STATUSCODE_GOOD;
49979}
49980
49981/* According to OPC Unified Architecture, Part 4 5.13.1.1 i) */
49982/* The value 0 is never used for the sequence number */
49983static UA_UInt32
49984UA_Client_Subscriptions_nextSequenceNumber(UA_UInt32 sequenceNumber) {
49985 UA_UInt32 nextSequenceNumber = sequenceNumber + 1;
49986 if(nextSequenceNumber == 0)
49987 nextSequenceNumber = 1;
49988 return nextSequenceNumber;
49989}
49990
49991static void
49992processDataChangeNotification(UA_Client *client, UA_Client_Subscription *sub,
49993 UA_DataChangeNotification *dataChangeNotification) {
49994 for(size_t j = 0; j < dataChangeNotification->monitoredItemsSize; ++j) {
49995 UA_MonitoredItemNotification *min = &dataChangeNotification->monitoredItems[j];
49996
49997 /* Find the MonitoredItem */
49998 UA_Client_MonitoredItem *mon;
49999 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
50000 if(mon->clientHandle == min->clientHandle)
50001 break;
50002 }
50003
50004 if(!mon) {
50005 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50006 msg: "Could not process a notification with clienthandle %" PRIu32
50007 " on subscription %" PRIu32, min->clientHandle, sub->subscriptionId);
50008 continue;
50009 }
50010
50011 if(mon->isEventMonitoredItem) {
50012 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50013 msg: "MonitoredItem is configured for Events. But received a "
50014 "DataChangeNotification.");
50015 continue;
50016 }
50017
50018 if(mon->handler.dataChangeCallback) {
50019 mon->handler.dataChangeCallback(client, sub->subscriptionId, sub->context,
50020 mon->monitoredItemId, mon->context,
50021 &min->value);
50022 }
50023 }
50024}
50025
50026static void
50027processEventNotification(UA_Client *client, UA_Client_Subscription *sub,
50028 UA_EventNotificationList *eventNotificationList) {
50029 for(size_t j = 0; j < eventNotificationList->eventsSize; ++j) {
50030 UA_EventFieldList *eventFieldList = &eventNotificationList->events[j];
50031
50032 /* Find the MonitoredItem */
50033 UA_Client_MonitoredItem *mon;
50034 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
50035 if(mon->clientHandle == eventFieldList->clientHandle)
50036 break;
50037 }
50038
50039 if(!mon) {
50040 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50041 msg: "Could not process a notification with clienthandle %" PRIu32
50042 " on subscription %" PRIu32, eventFieldList->clientHandle,
50043 sub->subscriptionId);
50044 continue;
50045 }
50046
50047 if(!mon->isEventMonitoredItem) {
50048 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50049 msg: "MonitoredItem is configured for DataChanges. But received a "
50050 "EventNotification.");
50051 continue;
50052 }
50053
50054 mon->handler.eventCallback(client, sub->subscriptionId, sub->context,
50055 mon->monitoredItemId, mon->context,
50056 eventFieldList->eventFieldsSize,
50057 eventFieldList->eventFields);
50058 }
50059}
50060
50061static void
50062processNotificationMessage(UA_Client *client, UA_Client_Subscription *sub,
50063 UA_ExtensionObject *msg) {
50064 if(msg->encoding != UA_EXTENSIONOBJECT_DECODED)
50065 return;
50066
50067 /* Handle DataChangeNotification */
50068 if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]) {
50069 UA_DataChangeNotification *dataChangeNotification =
50070 (UA_DataChangeNotification *)msg->content.decoded.data;
50071 processDataChangeNotification(client, sub, dataChangeNotification);
50072 return;
50073 }
50074
50075 /* Handle EventNotification */
50076 if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]) {
50077 UA_EventNotificationList *eventNotificationList =
50078 (UA_EventNotificationList *)msg->content.decoded.data;
50079 processEventNotification(client, sub, eventNotificationList);
50080 return;
50081 }
50082
50083 /* Handle StatusChangeNotification */
50084 if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]) {
50085 if(sub->statusChangeCallback) {
50086 sub->statusChangeCallback(client, sub->subscriptionId, sub->context,
50087 (UA_StatusChangeNotification*)msg->content.decoded.data);
50088 } else {
50089 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50090 msg: "Dropped a StatusChangeNotification since no "
50091 "callback is registered");
50092 }
50093 return;
50094 }
50095
50096 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50097 msg: "Unknown notification message type");
50098}
50099
50100static void
50101UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequest *request,
50102 UA_PublishResponse *response) {
50103 UA_NotificationMessage *msg = &response->notificationMessage;
50104
50105 client->currentlyOutStandingPublishRequests--;
50106
50107 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS) {
50108 if(client->config.outStandingPublishRequests > 1) {
50109 client->config.outStandingPublishRequests--;
50110 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50111 msg: "Too many publishrequest, reduce outStandingPublishRequests "
50112 "to %" PRId16, client->config.outStandingPublishRequests);
50113 } else {
50114 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50115 msg: "Too many publishrequest when outStandingPublishRequests = 1");
50116 UA_Client_Subscriptions_deleteSingle(client, subscriptionId: response->subscriptionId);
50117 }
50118 return;
50119 }
50120
50121 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSHUTDOWN)
50122 return;
50123
50124 if(!LIST_FIRST(&client->subscriptions)) {
50125 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
50126 return;
50127 }
50128
50129 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONCLOSED) {
50130 if(client->sessionState != UA_SESSIONSTATE_ACTIVATED) {
50131 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50132 msg: "Received Publish Response with code %s",
50133 UA_StatusCode_name(code: response->responseHeader.serviceResult));
50134 UA_Client_Subscription* sub = findSubscription(client, subscriptionId: response->subscriptionId);
50135 if (sub != NULL)
50136 UA_Client_Subscription_deleteInternal(client, sub);
50137 }
50138 return;
50139 }
50140
50141 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONIDINVALID) {
50142 UA_Client_disconnect(client); /* TODO: This should be handled before the process callback */
50143 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50144 msg: "Received BadSessionIdInvalid");
50145 return;
50146 }
50147
50148 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) {
50149 if (client->config.subscriptionInactivityCallback) {
50150 UA_Client_Subscription* sub = findSubscription(client, subscriptionId: response->subscriptionId);
50151 if (sub != NULL)
50152 client->config.subscriptionInactivityCallback(client, sub->subscriptionId,
50153 sub->context);
50154 }
50155 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50156 msg: "Received Timeout for Publish Response");
50157 return;
50158 }
50159
50160 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
50161 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50162 msg: "Received Publish Response with code %s",
50163 UA_StatusCode_name(code: response->responseHeader.serviceResult));
50164 return;
50165 }
50166
50167 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: response->subscriptionId);
50168 if(!sub) {
50169 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
50170 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50171 msg: "Received Publish Response for a non-existant subscription");
50172 return;
50173 }
50174
50175 sub->lastActivity = UA_DateTime_nowMonotonic();
50176
50177 /* Detect missing message - OPC Unified Architecture, Part 4 5.13.1.1 e) */
50178 if(UA_Client_Subscriptions_nextSequenceNumber(sequenceNumber: sub->sequenceNumber) != msg->sequenceNumber) {
50179 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50180 msg: "Invalid subscription sequence number: expected %" PRIu32
50181 " but got %" PRIu32,
50182 UA_Client_Subscriptions_nextSequenceNumber(sequenceNumber: sub->sequenceNumber),
50183 msg->sequenceNumber);
50184 /* This is an error. But we do not abort the connection. Some server
50185 * SDKs misbehave from time to time and send out-of-order sequence
50186 * numbers. (Probably some multi-threading synchronization issue.) */
50187 /* UA_Client_disconnect(client);
50188 return; */
50189 }
50190 /* According to f), a keep-alive message contains no notifications and has
50191 * the sequence number of the next NotificationMessage that is to be sent =>
50192 * More than one consecutive keep-alive message or a NotificationMessage
50193 * following a keep-alive message will share the same sequence number. */
50194 if (msg->notificationDataSize)
50195 sub->sequenceNumber = msg->sequenceNumber;
50196
50197 /* Process the notification messages */
50198 for(size_t k = 0; k < msg->notificationDataSize; ++k)
50199 processNotificationMessage(client, sub, msg: &msg->notificationData[k]);
50200
50201 /* Add to the list of pending acks */
50202 for(size_t i = 0; i < response->availableSequenceNumbersSize; i++) {
50203 if(response->availableSequenceNumbers[i] != msg->sequenceNumber)
50204 continue;
50205 UA_Client_NotificationsAckNumber *tmpAck = (UA_Client_NotificationsAckNumber*)
50206 UA_malloc(size: sizeof(UA_Client_NotificationsAckNumber));
50207 if(!tmpAck) {
50208 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50209 msg: "Not enough memory to store the acknowledgement for a publish "
50210 "message on subscription %" PRIu32, sub->subscriptionId);
50211 break;
50212 }
50213 tmpAck->subAck.sequenceNumber = msg->sequenceNumber;
50214 tmpAck->subAck.subscriptionId = sub->subscriptionId;
50215 LIST_INSERT_HEAD(&client->pendingNotificationsAcks, tmpAck, listEntry);
50216 break;
50217 }
50218}
50219
50220static void
50221processPublishResponseAsync(UA_Client *client, void *userdata,
50222 UA_UInt32 requestId, void *response) {
50223 UA_PublishRequest *req = (UA_PublishRequest*)userdata;
50224 UA_PublishResponse *res = (UA_PublishResponse*)response;
50225
50226 /* Process the response */
50227 UA_Client_Subscriptions_processPublishResponse(client, request: req, response: res);
50228
50229 /* Delete the cached request */
50230 UA_PublishRequest_delete(p: req);
50231
50232 /* Fill up the outstanding publish requests */
50233 UA_Client_Subscriptions_backgroundPublish(client);
50234}
50235
50236void
50237UA_Client_Subscriptions_clean(UA_Client *client) {
50238 UA_Client_NotificationsAckNumber *n;
50239 UA_Client_NotificationsAckNumber *tmp;
50240 LIST_FOREACH_SAFE(n, &client->pendingNotificationsAcks, listEntry, tmp) {
50241 LIST_REMOVE(n, listEntry);
50242 UA_free(ptr: n);
50243 }
50244
50245 UA_Client_Subscription *sub;
50246 UA_Client_Subscription *tmps;
50247 LIST_FOREACH_SAFE(sub, &client->subscriptions, listEntry, tmps)
50248 UA_Client_Subscription_deleteInternal(client, sub); /* force local removal */
50249
50250 client->monitoredItemHandles = 0;
50251}
50252
50253void
50254UA_Client_Subscriptions_backgroundPublishInactivityCheck(UA_Client *client) {
50255 if(client->sessionState < UA_SESSIONSTATE_ACTIVATED)
50256 return;
50257
50258 /* Is the lack of responses the client's fault? */
50259 if(client->currentlyOutStandingPublishRequests == 0)
50260 return;
50261
50262 UA_Client_Subscription *sub;
50263 LIST_FOREACH(sub, &client->subscriptions, listEntry) {
50264 UA_DateTime maxSilence = (UA_DateTime)
50265 ((sub->publishingInterval * sub->maxKeepAliveCount) +
50266 client->config.timeout) * UA_DATETIME_MSEC;
50267 if(maxSilence + sub->lastActivity < UA_DateTime_nowMonotonic()) {
50268 /* Reset activity */
50269 sub->lastActivity = UA_DateTime_nowMonotonic();
50270
50271 if(client->config.subscriptionInactivityCallback)
50272 client->config.subscriptionInactivityCallback(client, sub->subscriptionId,
50273 sub->context);
50274 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50275 msg: "Inactivity for Subscription %" PRIu32 ".", sub->subscriptionId);
50276 }
50277 }
50278}
50279
50280void
50281UA_Client_Subscriptions_backgroundPublish(UA_Client *client) {
50282 if(client->sessionState != UA_SESSIONSTATE_ACTIVATED)
50283 return;
50284
50285 /* The session must have at least one subscription */
50286 if(!LIST_FIRST(&client->subscriptions))
50287 return;
50288
50289 while(client->currentlyOutStandingPublishRequests < client->config.outStandingPublishRequests) {
50290 UA_PublishRequest *request = UA_PublishRequest_new();
50291 if(!request)
50292 return;
50293
50294 request->requestHeader.timeoutHint=60000;
50295 UA_StatusCode retval = UA_Client_preparePublishRequest(client, request);
50296 if(retval != UA_STATUSCODE_GOOD) {
50297 UA_PublishRequest_delete(p: request);
50298 return;
50299 }
50300
50301 UA_UInt32 requestId;
50302 client->currentlyOutStandingPublishRequests++;
50303
50304 /* Disable the timeout, it is treat in
50305 * UA_Client_Subscriptions_backgroundPublishInactivityCheck */
50306 retval = __UA_Client_AsyncServiceEx(client, request,
50307 requestType: &UA_TYPES[UA_TYPES_PUBLISHREQUEST],
50308 callback: processPublishResponseAsync,
50309 responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE],
50310 userdata: (void*)request, requestId: &requestId, timeout: 0);
50311 if(retval != UA_STATUSCODE_GOOD) {
50312 UA_PublishRequest_delete(p: request);
50313 return;
50314 }
50315 }
50316}
50317
50318#endif /* UA_ENABLE_SUBSCRIPTIONS */
50319
50320/**** amalgamated original file "/deps/libc_time.c" ****/
50321
50322/* Originally released by the musl project (http://www.musl-libc.org/) under the
50323 * MIT license. Taken from the file /src/time/__secs_to_tm.c */
50324
50325#include <limits.h>
50326
50327/* 2000-03-01 (mod 400 year, immediately after feb29 */
50328#define LEAPOCH (946684800LL + 86400*(31+29))
50329
50330#define DAYS_PER_400Y (365*400 + 97)
50331#define DAYS_PER_100Y (365*100 + 24)
50332#define DAYS_PER_4Y (365*4 + 1)
50333
50334int __secs_to_tm(long long t, struct mytm *tm) {
50335 long long days, secs, years;
50336 int remdays, remsecs, remyears;
50337 int qc_cycles, c_cycles, q_cycles;
50338 int months;
50339 static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29};
50340
50341 /* Reject time_t values whose year would overflow int */
50342 if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL)
50343 return -1;
50344
50345 secs = t - LEAPOCH;
50346 days = secs / 86400LL;
50347 remsecs = (int)(secs % 86400);
50348 if (remsecs < 0) {
50349 remsecs += 86400;
50350 --days;
50351 }
50352
50353 qc_cycles = (int)(days / DAYS_PER_400Y);
50354 remdays = (int)(days % DAYS_PER_400Y);
50355 if (remdays < 0) {
50356 remdays += DAYS_PER_400Y;
50357 --qc_cycles;
50358 }
50359
50360 c_cycles = remdays / DAYS_PER_100Y;
50361 if (c_cycles == 4) --c_cycles;
50362 remdays -= c_cycles * DAYS_PER_100Y;
50363
50364 q_cycles = remdays / DAYS_PER_4Y;
50365 if (q_cycles == 25) --q_cycles;
50366 remdays -= q_cycles * DAYS_PER_4Y;
50367
50368 remyears = remdays / 365;
50369 if (remyears == 4) --remyears;
50370 remdays -= remyears * 365;
50371
50372 years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles;
50373
50374 for (months=0; days_in_month[months] <= remdays; ++months)
50375 remdays -= days_in_month[months];
50376
50377 if (years+100 > INT_MAX || years+100 < INT_MIN)
50378 return -1;
50379
50380 tm->tm_year = (int)(years + 100);
50381 tm->tm_mon = months + 2;
50382 if (tm->tm_mon >= 12) {
50383 tm->tm_mon -=12;
50384 ++tm->tm_year;
50385 }
50386 tm->tm_mday = remdays + 1;
50387 tm->tm_hour = remsecs / 3600;
50388 tm->tm_min = remsecs / 60 % 60;
50389 tm->tm_sec = remsecs % 60;
50390
50391 return 0;
50392}
50393
50394static const int secs_through_month[] =
50395 {0, 31*86400, 59*86400, 90*86400,
50396 120*86400, 151*86400, 181*86400, 212*86400,
50397 243*86400, 273*86400, 304*86400, 334*86400 };
50398
50399static int
50400__month_to_secs(int month, int is_leap) {
50401 int t = secs_through_month[month];
50402 if (is_leap && month >= 2)
50403 t+=86400;
50404 return t;
50405}
50406
50407static long long
50408__year_to_secs(const long long year, int *is_leap) {
50409 int cycles, centuries, leaps, rem;
50410 int is_leap_val = 0;
50411 if (!is_leap) {
50412 is_leap = &is_leap_val;
50413 }
50414 cycles = (int)((year-100) / 400);
50415 rem = (int)((year-100) % 400);
50416 if (rem < 0) {
50417 cycles--;
50418 rem += 400;
50419 }
50420 if (!rem) {
50421 *is_leap = 1;
50422 centuries = 0;
50423 leaps = 0;
50424 } else {
50425 if (rem >= 200) {
50426 if (rem >= 300) centuries = 3, rem -= 300;
50427 else centuries = 2, rem -= 200;
50428 } else {
50429 if (rem >= 100) centuries = 1, rem -= 100;
50430 else centuries = 0;
50431 }
50432 if (!rem) {
50433 *is_leap = 0;
50434 leaps = 0;
50435 } else {
50436 leaps = (rem / (int)4U);
50437 rem %= (int)4U;
50438 *is_leap = !rem;
50439 }
50440 }
50441
50442 leaps += 97*cycles + 24*centuries - *is_leap;
50443
50444 return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
50445}
50446
50447long long __tm_to_secs(const struct mytm *tm) {
50448 int is_leap;
50449 long long year = tm->tm_year;
50450 int month = tm->tm_mon;
50451 if (month >= 12 || month < 0) {
50452 int adj = month / 12;
50453 month %= 12;
50454 if (month < 0) {
50455 adj--;
50456 month += 12;
50457 }
50458 year += adj;
50459 }
50460 long long t = __year_to_secs(year, is_leap: &is_leap);
50461 t += __month_to_secs(month, is_leap);
50462 t += 86400LL * (tm->tm_mday-1);
50463 t += 3600LL * tm->tm_hour;
50464 t += 60LL * tm->tm_min;
50465 t += tm->tm_sec;
50466 return t;
50467}
50468
50469/**** amalgamated original file "/deps/pcg_basic.c" ****/
50470
50471/*
50472 * PCG Random Number Generation for C.
50473 *
50474 * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
50475 *
50476 * Licensed under the Apache License, Version 2.0 (the "License");
50477 * you may not use this file except in compliance with the License.
50478 * You may obtain a copy of the License at
50479 *
50480 * http://www.apache.org/licenses/LICENSE-2.0
50481 *
50482 * Unless required by applicable law or agreed to in writing, software
50483 * distributed under the License is distributed on an "AS IS" BASIS,
50484 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
50485 * See the License for the specific language governing permissions and
50486 * limitations under the License.
50487 *
50488 * For additional information about the PCG random number generation scheme,
50489 * including its license and other licensing options, visit
50490 *
50491 * http://www.pcg-random.org
50492 */
50493
50494
50495void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initial_state, uint64_t initseq) {
50496 rng->state = 0U;
50497 rng->inc = (initseq << 1u) | 1u;
50498 pcg32_random_r(rng);
50499 rng->state += initial_state;
50500 pcg32_random_r(rng);
50501}
50502
50503uint32_t pcg32_random_r(pcg32_random_t* rng) {
50504 uint64_t oldstate = rng->state;
50505 rng->state = oldstate * 6364136223846793005ULL + rng->inc;
50506 uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u);
50507 uint32_t rot = (uint32_t)(oldstate >> 59u);
50508 return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31)); /* was (xorshifted >> rot) | (xorshifted << ((-rot) & 31)) */
50509}
50510
50511/**** amalgamated original file "/deps/base64.c" ****/
50512
50513/*
50514 * Base64 encoding: Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
50515 * This software may be distributed under the terms of the BSD license.
50516 *
50517 * Base64 decoding: Copyright (c) 2016, polfosol
50518 * Posted at https://stackoverflow.com/a/37109258 under the CC-BY-SA Creative
50519 * Commons license.
50520 */
50521
50522
50523static const unsigned char base64_table[65] =
50524 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
50525
50526unsigned char *
50527UA_base64(const unsigned char *src, size_t len, size_t *out_len) {
50528 if(len == 0) {
50529 *out_len = 0;
50530 return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
50531 }
50532
50533 size_t olen = 4*((len + 2) / 3); /* 3-byte blocks to 4-byte */
50534 if(olen < len)
50535 return NULL; /* integer overflow */
50536
50537 unsigned char *out = (unsigned char*)UA_malloc(size: olen);
50538 if(!out)
50539 return NULL;
50540
50541 const unsigned char *end = src + len;
50542 const unsigned char *in = src;
50543 unsigned char *pos = out;
50544 while(end - in >= 3) {
50545 *pos++ = base64_table[in[0] >> 2];
50546 *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
50547 *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
50548 *pos++ = base64_table[in[2] & 0x3f];
50549 in += 3;
50550 }
50551
50552 if(end - in) {
50553 *pos++ = base64_table[in[0] >> 2];
50554 if(end - in == 1) {
50555 *pos++ = base64_table[(in[0] & 0x03) << 4];
50556 *pos++ = '=';
50557 } else {
50558 *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
50559 *pos++ = base64_table[(in[1] & 0x0f) << 2];
50560 }
50561 *pos++ = '=';
50562 }
50563
50564 *out_len = (size_t)(pos - out);
50565 return out;
50566}
50567
50568static const uint32_t from_b64[256] = {
50569 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50570 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50571 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63,
50572 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
50573 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
50574 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63,
50575 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
50576 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
50577
50578unsigned char *
50579UA_unbase64(const unsigned char *src, size_t len, size_t *out_len) {
50580 // we need a minimum length
50581 if(len <= 2) {
50582 *out_len = 0;
50583 return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
50584 }
50585
50586 const unsigned char *p = src;
50587 size_t pad1 = len % 4 || p[len - 1] == '=';
50588 size_t pad2 = pad1 && (len % 4 > 2 || p[len - 2] != '=');
50589 const size_t last = (len - pad1) / 4 << 2;
50590
50591 unsigned char *str = (unsigned char*)UA_malloc(size: last / 4 * 3 + pad1 + pad2);
50592 if(!str)
50593 return NULL;
50594
50595 unsigned char *pos = str;
50596 for(size_t i = 0; i < last; i += 4) {
50597 uint32_t n = from_b64[p[i]] << 18 | from_b64[p[i + 1]] << 12 |
50598 from_b64[p[i + 2]] << 6 | from_b64[p[i + 3]];
50599 *pos++ = (unsigned char)(n >> 16);
50600 *pos++ = (unsigned char)(n >> 8 & 0xFF);
50601 *pos++ = (unsigned char)(n & 0xFF);
50602 }
50603
50604 if(pad1) {
50605 if (last + 1 >= len) {
50606 UA_free(ptr: str);
50607 *out_len = 0;
50608 return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
50609 }
50610 uint32_t n = from_b64[p[last]] << 18 | from_b64[p[last + 1]] << 12;
50611 *pos++ = (unsigned char)(n >> 16);
50612 if(pad2) {
50613 if (last + 2 >= len) {
50614 UA_free(ptr: str);
50615 *out_len = 0;
50616 return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
50617 }
50618 n |= from_b64[p[last + 2]] << 6;
50619 *pos++ = (unsigned char)(n >> 8 & 0xFF);
50620 }
50621 }
50622
50623 *out_len = (uintptr_t)(pos - str);
50624 return str;
50625}
50626
50627/**** amalgamated original file "/deps/aa_tree.c" ****/
50628
50629/* This Source Code Form is subject to the terms of the Mozilla Public
50630 * License, v. 2.0. If a copy of the MPL was not distributed with this
50631 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
50632 *
50633 * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
50634 */
50635
50636#include <stddef.h>
50637
50638#ifdef UNDER_CE
50639 /* Windows CE: uintptr_t has already been defined by windows.h */
50640#elif !defined(_MSC_VER) || _MSC_VER >= 1800
50641# include <inttypes.h>
50642#elif !defined(uintptr_t)
50643 /* Workaround missing standard includes in older Visual Studio */
50644# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
50645typedef _W64 unsigned int uintptr_t;
50646# else
50647typedef unsigned __int64 uintptr_t;
50648# endif
50649#endif
50650
50651#define aa_entry_container(head, entry) \
50652 ((void*)((uintptr_t)entry - head->entry_offset))
50653#define aa_entry_key(head, entry) \
50654 ((const void*)((uintptr_t)entry + head->key_offset - head->entry_offset))
50655#define aa_container_entry(head, container) \
50656 ((struct aa_entry*)((uintptr_t)container + head->entry_offset))
50657#define aa_container_key(head, container) \
50658 ((const void*)((uintptr_t)container + head->key_offset))
50659
50660void
50661aa_init(struct aa_head *head,
50662 enum aa_cmp (*cmp)(const void*, const void*),
50663 unsigned int entry_offset, unsigned int key_offset) {
50664 head->root = NULL;
50665 head->cmp = cmp;
50666 head->entry_offset = entry_offset;
50667 head->key_offset = key_offset;
50668}
50669
50670static struct aa_entry *
50671_aa_skew(struct aa_entry *n) {
50672 if(!n)
50673 return NULL;
50674 if(n->left && n->level == n->left->level) {
50675 struct aa_entry *l = n->left;
50676 n->left = l->right;
50677 l->right = n;
50678 return l;
50679 }
50680 return n;
50681}
50682
50683static struct aa_entry *
50684_aa_split(struct aa_entry *n) {
50685 if(!n)
50686 return NULL;
50687 if(n->right && n->right->right &&
50688 n->right->right->level == n->level) {
50689 struct aa_entry *r = n->right;
50690 n->right = r->left;
50691 r->left = n;
50692 r->level++;
50693 return r;
50694 }
50695 return n;
50696}
50697
50698static struct aa_entry *
50699_aa_fixup(struct aa_entry *n) {
50700 unsigned int should_be = 0;
50701 if(n->left)
50702 should_be = n->left->level;
50703 if(n->right && n->right->level < should_be)
50704 should_be = n->right->level;
50705 should_be++;
50706 if(should_be < n->level)
50707 n->level = should_be;
50708 if(n->right && n->right->level > should_be)
50709 n->right->level = should_be;
50710 n = _aa_skew(n);
50711 n->right = _aa_skew(n: n->right);
50712 if(n->right)
50713 n->right->right = _aa_skew(n: n->right->right);
50714 n = _aa_split(n);
50715 n->right = _aa_split(n: n->right);
50716 return n;
50717}
50718
50719static struct aa_entry *
50720_aa_insert(struct aa_head *h, struct aa_entry *n, void *elem) {
50721 if(!n) {
50722 struct aa_entry *e = aa_container_entry(h, elem);
50723 e->left = NULL;
50724 e->right = NULL;
50725 e->level = 1;
50726 return e;
50727 }
50728 const void *n_key = aa_entry_key(h, n);
50729 const void *key = aa_container_key(h, elem);
50730 enum aa_cmp eq = h->cmp(key, n_key);
50731 if(eq == AA_CMP_EQ)
50732 eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
50733 if(eq == AA_CMP_LESS)
50734 n->left = _aa_insert(h, n: n->left, elem);
50735 else
50736 n->right = _aa_insert(h, n: n->right, elem);
50737 return _aa_split(n: _aa_skew(n));
50738}
50739
50740void
50741aa_insert(struct aa_head *h, void *elem) {
50742 h->root = _aa_insert(h, n: h->root, elem);
50743}
50744
50745void *
50746aa_find(const struct aa_head *h, const void *key) {
50747 struct aa_entry *n = h->root;
50748 while(n) {
50749 enum aa_cmp eq = h->cmp(key, aa_entry_key(h, n));
50750 if(eq == AA_CMP_EQ)
50751 return aa_entry_container(h, n);
50752 n = (eq == AA_CMP_LESS) ? n->left : n->right;
50753 }
50754 return NULL;
50755}
50756
50757static struct aa_entry *
50758unlink_succ(struct aa_entry *n, struct aa_entry **succ) {
50759 if(!n->left) {
50760 *succ = n;
50761 return n->right;
50762 }
50763 n->left = unlink_succ(n: n->left, succ);
50764 return _aa_fixup(n);
50765}
50766
50767static struct aa_entry *
50768unlink_pred(struct aa_entry *n, struct aa_entry **pred) {
50769 if(!n->right) {
50770 *pred = n;
50771 return n->left;
50772 }
50773 n->right = unlink_pred(n: n->right, pred);
50774 return _aa_fixup(n);
50775}
50776
50777static struct aa_entry *
50778_aa_remove(struct aa_head *h, void *elem, struct aa_entry *n) {
50779 if(!n)
50780 return NULL;
50781
50782 const void *elem_key = aa_container_key(h, elem);
50783 const void *n_key = aa_entry_key(h, n);
50784 if(n_key == elem_key) {
50785 if(!n->left && !n->right)
50786 return NULL;
50787 struct aa_entry *replace = NULL;
50788 if(!n->left)
50789 n->right = unlink_succ(n: n->right, succ: &replace);
50790 else
50791 n->left = unlink_pred(n: n->left, pred: &replace);
50792 replace->left = n->left;
50793 replace->right = n->right;
50794 replace->level = n->level;
50795 return _aa_fixup(n: replace);
50796 }
50797
50798 enum aa_cmp eq = h->cmp(elem_key, n_key);
50799 if(eq == AA_CMP_EQ)
50800 eq = (elem_key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
50801 if(eq == AA_CMP_LESS)
50802 n->left = _aa_remove(h, elem, n: n->left);
50803 else
50804 n->right = _aa_remove(h, elem, n: n->right);
50805 return _aa_fixup(n);
50806}
50807
50808void
50809aa_remove(struct aa_head *head, void *elem) {
50810 head->root = _aa_remove(h: head, elem, n: head->root);
50811}
50812
50813void *
50814aa_min(const struct aa_head *head) {
50815 struct aa_entry *e = head->root;
50816 if(!e)
50817 return NULL;
50818 while(e->left)
50819 e = e->left;
50820 return aa_entry_container(head, e);
50821}
50822
50823void *
50824aa_max(const struct aa_head *head) {
50825 struct aa_entry *e = head->root;
50826 if(!e)
50827 return NULL;
50828 while(e->right)
50829 e = e->right;
50830 return aa_entry_container(head, e);
50831}
50832
50833void *
50834aa_next(const struct aa_head *head, const void *elem) {
50835 struct aa_entry *e = aa_container_entry(head, elem);
50836 if(e->right) {
50837 e = e->right;
50838 while(e->left)
50839 e = e->left;
50840 return aa_entry_container(head, e);
50841 }
50842 struct aa_entry *next = NULL;
50843 struct aa_entry *n = head->root;
50844 const void *key = aa_container_key(head, elem);
50845 while(n && n != e) {
50846 const void *n_key = aa_entry_key(head, n);
50847 enum aa_cmp eq = head->cmp(key, n_key);
50848 if(eq == AA_CMP_EQ)
50849 eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
50850 if(eq == AA_CMP_MORE) {
50851 n = n->right;
50852 } else {
50853 next = n;
50854 n = n->left;
50855 }
50856 }
50857 return (next) ? aa_entry_container(head, next) : NULL;
50858}
50859
50860void *
50861aa_prev(const struct aa_head *head, const void *elem) {
50862 struct aa_entry *e = aa_container_entry(head, elem);
50863 if(e->left) {
50864 e = e->left;
50865 while(e->right)
50866 e = e->right;
50867 return aa_entry_container(head, e);
50868 }
50869 struct aa_entry *prev = NULL;
50870 struct aa_entry *n = head->root;
50871 const void *key = aa_container_key(head, elem);
50872 while(n && n != e) {
50873 const void *n_key = aa_entry_key(head, n);
50874 enum aa_cmp eq = head->cmp(key, n_key);
50875 if(eq == AA_CMP_EQ)
50876 eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
50877 if(eq == AA_CMP_MORE) {
50878 prev = n;
50879 n = n->right;
50880 } else {
50881 n = n->left;
50882 }
50883 }
50884 return (prev) ? aa_entry_container(head, prev) : NULL;
50885}
50886
50887/**** amalgamated original file "/deps/ziptree.c" ****/
50888
50889/* This Source Code Form is subject to the terms of the Mozilla Public
50890 * License, v. 2.0. If a copy of the MPL was not distributed with this
50891 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
50892 *
50893 * Copyright 2021 (c) Julius Pfrommer
50894 */
50895
50896
50897#if defined(_MSC_VER)
50898#include <intrin.h>
50899#endif
50900
50901unsigned char
50902__ZIP_FFS32(unsigned int v) {
50903#if defined(__GNUC__) || defined(__clang__)
50904 return (unsigned char)((unsigned char)__builtin_ffs((int)v) - 1u);
50905#elif defined(_MSC_VER)
50906 unsigned long index = 255;
50907 _BitScanForward(&index, v);
50908 return (unsigned char)index;
50909#else
50910 if(v == 0)
50911 return 255;
50912 unsigned int t = 1;
50913 unsigned char r = 0;
50914 while((v & t) == 0) {
50915 t = t << 1;
50916 r++;
50917 }
50918 return r;
50919#endif
50920}
50921
50922/* Generic analog to ZIP_ENTRY(type) */
50923struct zip_entry {
50924 void *left;
50925 void *right;
50926 unsigned char rank;
50927};
50928
50929#define ZIP_ENTRY_PTR(x) (struct zip_entry*)((char*)x + fieldoffset)
50930#define ZIP_KEY_PTR(x) (void*)((char*)x + keyoffset)
50931
50932void *
50933__ZIP_INSERT(zip_cmp_cb cmp, unsigned short fieldoffset,
50934 unsigned short keyoffset, void *root, void *elm) {
50935 struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
50936 struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
50937 if(!root) {
50938 elm_entry->left = NULL;
50939 elm_entry->right = NULL;
50940 return elm;
50941 }
50942 enum ZIP_CMP order = cmp(ZIP_KEY_PTR(elm), ZIP_KEY_PTR(root));
50943 if(order == ZIP_CMP_LESS) {
50944 if(__ZIP_INSERT(cmp, fieldoffset, keyoffset, root: root_entry->left, elm) == elm) {
50945 if(elm_entry->rank < root_entry->rank) {
50946 root_entry->left = elm;
50947 } else {
50948 root_entry->left = elm_entry->right;
50949 elm_entry->right = root;
50950 return elm;
50951 }
50952 }
50953 } else {
50954 if(__ZIP_INSERT(cmp, fieldoffset, keyoffset, root: root_entry->right, elm) == elm) {
50955 if(elm_entry->rank <= root_entry->rank) {
50956 root_entry->right = elm;
50957 } else {
50958 root_entry->right = elm_entry->left;
50959 elm_entry->left = root;
50960 return elm;
50961 }
50962 }
50963 }
50964 return root;
50965}
50966
50967static void *
50968__ZIP(unsigned short fieldoffset, void *x, void *y) {
50969 if(!x) return y;
50970 if(!y) return x;
50971 struct zip_entry *x_entry = ZIP_ENTRY_PTR(x);
50972 struct zip_entry *y_entry = ZIP_ENTRY_PTR(y);
50973 if(x_entry->rank < y_entry->rank) {
50974 y_entry->left = __ZIP(fieldoffset, x, y: y_entry->left);
50975 return y;
50976 } else {
50977 x_entry->right = __ZIP(fieldoffset, x: x_entry->right, y);
50978 return x;
50979 }
50980}
50981
50982/* Modified from the original algorithm. Allow multiple elements with the same
50983 * key. */
50984void *
50985__ZIP_REMOVE(zip_cmp_cb cmp, unsigned short fieldoffset,
50986 unsigned short keyoffset, void *root, void *elm) {
50987 struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
50988 if(root == elm)
50989 return __ZIP(fieldoffset, x: root_entry->left, y: root_entry->right);
50990 void *left = root_entry->left;
50991 void *right = root_entry->right;
50992 enum ZIP_CMP eq = cmp(ZIP_KEY_PTR(elm), ZIP_KEY_PTR(root));
50993 if(eq == ZIP_CMP_LESS) {
50994 struct zip_entry *left_entry = ZIP_ENTRY_PTR(left);
50995 if(elm == left)
50996 root_entry->left = __ZIP(fieldoffset, x: left_entry->left, y: left_entry->right);
50997 else if(left)
50998 __ZIP_REMOVE(cmp, fieldoffset, keyoffset, root: left, elm);
50999 } else if(eq == ZIP_CMP_MORE) {
51000 struct zip_entry *right_entry = ZIP_ENTRY_PTR(right);
51001 if(elm == right)
51002 root_entry->right = __ZIP(fieldoffset, x: right_entry->left, y: right_entry->right);
51003 else if(right)
51004 __ZIP_REMOVE(cmp, fieldoffset, keyoffset, root: right, elm);
51005 } else { /* ZIP_CMP_EQ, but root != elm */
51006 if(right)
51007 root_entry->right = __ZIP_REMOVE(cmp, fieldoffset, keyoffset, root: right, elm);
51008 if(left)
51009 root_entry->left = __ZIP_REMOVE(cmp, fieldoffset, keyoffset, root: left, elm);
51010 }
51011 return root;
51012}
51013
51014void *
51015__ZIP_FIND(zip_cmp_cb cmp, unsigned short fieldoffset,
51016 unsigned short keyoffset, void *root, const void *key) {
51017 if(!root)
51018 return NULL;
51019 enum ZIP_CMP eq = cmp(key, ZIP_KEY_PTR(root));
51020 if(eq == ZIP_CMP_EQ)
51021 return root;
51022 struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
51023 if(eq == ZIP_CMP_LESS)
51024 return __ZIP_FIND(cmp, fieldoffset, keyoffset, root: root_entry->left, key);
51025 else
51026 return __ZIP_FIND(cmp, fieldoffset, keyoffset, root: root_entry->right, key);
51027}
51028
51029void *
51030__ZIP_MIN(unsigned short fieldoffset, void *elm) {
51031 if(!elm)
51032 return NULL;
51033 struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
51034 while(elm_entry->left) {
51035 elm = elm_entry->left;
51036 elm_entry = (struct zip_entry*)((char*)elm + fieldoffset);
51037 }
51038 return elm;
51039}
51040
51041void *
51042__ZIP_MAX(unsigned short fieldoffset, void *elm) {
51043 if(!elm)
51044 return NULL;
51045 struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
51046 while(elm_entry->right) {
51047 elm = elm_entry->right;
51048 elm_entry = (struct zip_entry*)((char*)elm + fieldoffset);
51049 }
51050 return elm;
51051}
51052
51053void
51054__ZIP_ITER(unsigned short fieldoffset, __zip_iter_cb cb,
51055 void *context, void *elm) {
51056 if(!elm)
51057 return;
51058 struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
51059 __ZIP_ITER(fieldoffset, cb, context, elm: elm_entry->left);
51060 __ZIP_ITER(fieldoffset, cb, context, elm: elm_entry->right);
51061 cb(elm, context);
51062}
51063
51064/**** amalgamated original file "/src/pubsub/ua_pubsub_config.c" ****/
51065
51066/* This Source Code Form is subject to the terms of the Mozilla Public
51067 * License, v. 2.0. If a copy of the MPL was not distributed with this
51068 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
51069 *
51070 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
51071 * Copyright (c) 2020 Thomas Fischer, Siemens AG
51072 */
51073
51074
51075#ifdef UA_ENABLE_PUBSUB
51076#ifdef UA_ENABLE_PUBSUB_ETH_UADP
51077#endif
51078#endif
51079
51080
51081#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
51082
51083static UA_StatusCode
51084createPubSubConnection(UA_Server *server,
51085 const UA_PubSubConnectionDataType *connection,
51086 UA_UInt32 pdsCount, UA_NodeId *pdsIdent);
51087
51088static UA_StatusCode
51089createWriterGroup(UA_Server *server,
51090 const UA_WriterGroupDataType *writerGroupParameters,
51091 UA_NodeId connectionIdent, UA_UInt32 pdsCount,
51092 const UA_NodeId *pdsIdent);
51093
51094static UA_StatusCode
51095createDataSetWriter(UA_Server *server,
51096 const UA_DataSetWriterDataType *dataSetWriterParameters,
51097 UA_NodeId writerGroupIdent, UA_UInt32 pdsCount,
51098 const UA_NodeId *pdsIdent);
51099
51100static UA_StatusCode
51101createReaderGroup(UA_Server *server,
51102 const UA_ReaderGroupDataType *readerGroupParameters,
51103 UA_NodeId connectionIdent);
51104
51105static UA_StatusCode
51106createDataSetReader(UA_Server *server,
51107 const UA_DataSetReaderDataType *dataSetReaderParameters,
51108 UA_NodeId readerGroupIdent);
51109
51110static UA_StatusCode
51111createPublishedDataSet(UA_Server *server,
51112 const UA_PublishedDataSetDataType *publishedDataSetParameters,
51113 UA_NodeId *publishedDataSetIdent);
51114
51115static UA_StatusCode
51116createDataSetFields(UA_Server *server,
51117 const UA_NodeId *publishedDataSetIdent,
51118 const UA_PublishedDataSetDataType *publishedDataSetParameters);
51119
51120static UA_StatusCode
51121generatePubSubConfigurationDataType(const UA_Server *server,
51122 UA_PubSubConfigurationDataType *pubSubConfiguration);
51123
51124/* Gets PubSub Configuration from an ExtensionObject */
51125static UA_StatusCode
51126extractPubSubConfigFromExtensionObject(const UA_ExtensionObject *src,
51127 UA_PubSubConfigurationDataType **dst) {
51128 if(src->encoding != UA_EXTENSIONOBJECT_DECODED ||
51129 src->content.decoded.type != &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE]) {
51130 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51131 "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
51132 "Reading extensionObject failed");
51133 return UA_STATUSCODE_BADINVALIDARGUMENT;
51134 }
51135
51136 UA_UABinaryFileDataType *binFile = (UA_UABinaryFileDataType*)src->content.decoded.data;
51137
51138 if(binFile->body.arrayLength != 0 || binFile->body.arrayDimensionsSize != 0) {
51139 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51140 "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
51141 "Loading multiple configurations is not supported");
51142 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51143 }
51144
51145 if(binFile->body.type != &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]) {
51146 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51147 "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
51148 "Invalid datatype encoded in the binary file");
51149 return UA_STATUSCODE_BADTYPEMISMATCH;
51150 }
51151
51152 *dst = (UA_PubSubConfigurationDataType*)binFile->body.data;
51153 return UA_STATUSCODE_GOOD;
51154}
51155
51156/* Configures a PubSub Server with given PubSubConfigurationDataType object */
51157static UA_StatusCode
51158updatePubSubConfig(UA_Server *server,
51159 const UA_PubSubConfigurationDataType *configurationParameters) {
51160 if(server == NULL || configurationParameters == NULL) {
51161 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51162 "[UA_PubSubManager_updatePubSubConfig] Invalid argument");
51163 return UA_STATUSCODE_BADINVALIDARGUMENT;
51164 }
51165
51166 UA_PubSubManager_delete(server, &server->pubSubManager);
51167
51168 /* Configuration of Published DataSets: */
51169 UA_UInt32 pdsCount = (UA_UInt32)configurationParameters->publishedDataSetsSize;
51170 UA_NodeId *publishedDataSetIdent = (UA_NodeId*)UA_calloc(pdsCount, sizeof(UA_NodeId));
51171 if(!publishedDataSetIdent)
51172 return UA_STATUSCODE_BADOUTOFMEMORY;
51173
51174 UA_StatusCode res = UA_STATUSCODE_GOOD;
51175 for(UA_UInt32 i = 0; i < pdsCount; i++) {
51176 res = createPublishedDataSet(server,
51177 &configurationParameters->publishedDataSets[i],
51178 &publishedDataSetIdent[i]);
51179 if(res != UA_STATUSCODE_GOOD) {
51180 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51181 "[UA_PubSubManager_updatePubSubConfig] PDS creation failed");
51182 UA_free(publishedDataSetIdent);
51183 return res;
51184 }
51185 }
51186
51187 /* Configuration of PubSub Connections: */
51188 if(configurationParameters->connectionsSize < 1) {
51189 UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51190 "[UA_PubSubManager_updatePubSubConfig] no connection in "
51191 "UA_PubSubConfigurationDataType");
51192 UA_free(publishedDataSetIdent);
51193 return UA_STATUSCODE_GOOD;
51194 }
51195
51196 for(size_t i = 0; i < configurationParameters->connectionsSize; i++) {
51197 res = createPubSubConnection(server,
51198 &configurationParameters->connections[i],
51199 pdsCount, publishedDataSetIdent);
51200 if(res != UA_STATUSCODE_GOOD)
51201 break;
51202 }
51203
51204 UA_free(publishedDataSetIdent);
51205 return res;
51206}
51207
51208/* Function called by UA_PubSubManager_createPubSubConnection to set the
51209 * PublisherId of a certain connection. */
51210static UA_StatusCode
51211setConnectionPublisherId(const UA_PubSubConnectionDataType *src,
51212 UA_PubSubConnectionConfig *dst) {
51213 if(src->publisherId.type == &UA_TYPES[UA_TYPES_STRING]) {
51214 dst->publisherIdType = UA_PUBSUB_PUBLISHERID_STRING;
51215 dst->publisherId.string = *(UA_String*)src->publisherId.data;
51216 } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_BYTE] ||
51217 src->publisherId.type == &UA_TYPES[UA_TYPES_UINT16] ||
51218 src->publisherId.type == &UA_TYPES[UA_TYPES_UINT32]) {
51219 dst->publisherIdType = UA_PUBSUB_PUBLISHERID_NUMERIC;
51220 dst->publisherId.numeric = *(UA_UInt32*)src->publisherId.data;
51221 } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_UINT64]) {
51222 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51223 "[UA_PubSubManager_setConnectionPublisherId] PublisherId is UInt64 "
51224 "(not implemented); Recommended dataType for PublisherId: UInt32");
51225 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51226 } else {
51227 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51228 "[UA_PubSubManager_setConnectionPublisherId] PublisherId is not valid.");
51229 return UA_STATUSCODE_BADINTERNALERROR;
51230 }
51231 return UA_STATUSCODE_GOOD;
51232}
51233
51234/* Function called by UA_PubSubManager_createPubSubConnection to create all WriterGroups
51235 * and ReaderGroups that belong to a certain connection. */
51236static UA_StatusCode
51237createComponentsForConnection(UA_Server *server,
51238 const UA_PubSubConnectionDataType *connParams,
51239 UA_NodeId connectionIdent, UA_UInt32 pdsCount,
51240 const UA_NodeId *pdsIdent) {
51241 /* WriterGroups configuration */
51242 UA_StatusCode res = UA_STATUSCODE_GOOD;
51243 for(size_t i = 0; i < connParams->writerGroupsSize; i++) {
51244 res = createWriterGroup(server, &connParams->writerGroups[i],
51245 connectionIdent, pdsCount, pdsIdent);
51246 if(res != UA_STATUSCODE_GOOD) {
51247 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51248 "[UA_PubSubManager_createComponentsForConnection] "
51249 "Error occured during %d. WriterGroup Creation", (UA_UInt32)i+1);
51250 return res;
51251 }
51252 }
51253
51254 /* ReaderGroups configuration */
51255 for(size_t j = 0; j < connParams->readerGroupsSize; j++) {
51256 res = createReaderGroup(server, &connParams->readerGroups[j], connectionIdent);
51257 if(res == UA_STATUSCODE_GOOD)
51258 res |= UA_PubSubConnection_regist(server, &connectionIdent);
51259 if(res != UA_STATUSCODE_GOOD) {
51260 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51261 "[UA_PubSubManager_createComponentsForConnection] "
51262 "Error occured during %d. ReaderGroup Creation", (UA_UInt32)j+1);
51263 return res;
51264 }
51265 }
51266
51267 return res;
51268}
51269
51270/* Checks if transportLayer for the specified transportProfileUri exists.
51271 *
51272 * @param server Server object that shall be configured
51273 * @param transportProfileUri String that specifies the transport protocol */
51274static UA_Boolean
51275transportLayerExists(UA_Server *server, UA_String transportProfileUri) {
51276 for(size_t i = 0; i < server->config.pubSubConfig.transportLayersSize; i++) {
51277 if(UA_String_equal(&server->config.pubSubConfig.transportLayers[i].transportProfileUri,
51278 &transportProfileUri)) {
51279 return true;
51280 }
51281 }
51282 return false;
51283}
51284
51285/* Creates transportlayer for specified transport protocol if this layer doesn't exist yet */
51286static UA_StatusCode
51287createTransportLayer(UA_Server *server, const UA_String transportProfileUri) {
51288 if(transportLayerExists(server, transportProfileUri))
51289 return UA_STATUSCODE_GOOD;
51290
51291 UA_ServerConfig *config = UA_Server_getConfig(server);
51292 UA_PubSubTransportLayer tl;
51293
51294 do {
51295 UA_String strUDP =
51296 UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
51297 if(UA_String_equal(&transportProfileUri, &strUDP)) {
51298 tl = UA_PubSubTransportLayerUDPMP();
51299 break;
51300 }
51301
51302#ifdef UA_ENABLE_PUBSUB_ETH_UADP
51303 UA_String strETH =
51304 UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-eth-uadp");
51305 if(UA_String_equal(&transportProfileUri, &strETH)) {
51306 tl = UA_PubSubTransportLayerEthernet();
51307 break;
51308 }
51309#endif
51310
51311 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51312 "[UA_PubSubManager_createTransportLayer] "
51313 "invalid transportProfileUri");
51314 return UA_STATUSCODE_BADINVALIDARGUMENT;
51315 } while(0);
51316
51317 if(config->pubSubConfig.transportLayersSize > 0) {
51318 config->pubSubConfig.transportLayers = (UA_PubSubTransportLayer *)
51319 UA_realloc(config->pubSubConfig.transportLayers,
51320 (config->pubSubConfig.transportLayersSize + 1) *
51321 sizeof(UA_PubSubTransportLayer));
51322 } else {
51323 config->pubSubConfig.transportLayers = (UA_PubSubTransportLayer *)
51324 UA_calloc(1, sizeof(UA_PubSubTransportLayer));
51325 }
51326
51327 if(config->pubSubConfig.transportLayers == NULL) {
51328 UA_Server_delete(server);
51329 return UA_STATUSCODE_BADOUTOFMEMORY;
51330 }
51331 config->pubSubConfig.transportLayers[config->pubSubConfig.transportLayersSize] = tl;
51332 config->pubSubConfig.transportLayersSize++;
51333 return UA_STATUSCODE_GOOD;
51334}
51335
51336/* Creates PubSubConnection configuration from PubSubConnectionDataType object
51337 *
51338 * @param server Server object that shall be configured
51339 * @param connParams PubSub connection configuration
51340 * @param pdsCount Number of published DataSets
51341 * @param pdsIdent Array of NodeIds of the published DataSets */
51342static UA_StatusCode
51343createPubSubConnection(UA_Server *server, const UA_PubSubConnectionDataType *connParams,
51344 UA_UInt32 pdsCount, UA_NodeId *pdsIdent) {
51345 UA_PubSubConnectionConfig config;
51346 memset(&config, 0, sizeof(UA_PubSubConnectionConfig));
51347
51348 config.name = connParams->name;
51349 config.enabled = connParams->enabled;
51350 config.transportProfileUri = connParams->transportProfileUri;
51351 config.connectionPropertiesSize = connParams->connectionPropertiesSize;
51352 if(config.connectionPropertiesSize > 0) {
51353 config.connectionProperties = connParams->connectionProperties;
51354 }
51355
51356 UA_StatusCode res = setConnectionPublisherId(connParams, &config);
51357 if(res != UA_STATUSCODE_GOOD) {
51358 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51359 "[UA_PubSubManager_createPubSubConnection] "
51360 "Setting PublisherId failed");
51361 return res;
51362 }
51363
51364 if(connParams->address.encoding == UA_EXTENSIONOBJECT_DECODED) {
51365 UA_Variant_setScalar(&(config.address),
51366 connParams->address.content.decoded.data,
51367 connParams->address.content.decoded.type);
51368 } else {
51369 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51370 "[UA_PubSubManager_createPubSubConnection] "
51371 "Reading connection address failed");
51372 return UA_STATUSCODE_BADINTERNALERROR;
51373 }
51374
51375 if(connParams->transportSettings.encoding == UA_EXTENSIONOBJECT_DECODED) {
51376 UA_Variant_setScalar(&(config.connectionTransportSettings),
51377 connParams->transportSettings.content.decoded.data,
51378 connParams->transportSettings.content.decoded.type);
51379 } else {
51380 UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51381 "[UA_PubSubManager_createPubSubConnection] "
51382 "TransportSettings can not be read");
51383 }
51384
51385 res = createTransportLayer(server, connParams->transportProfileUri);
51386 if(res != UA_STATUSCODE_GOOD) {
51387 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51388 "[UA_PubSubManager_createPubSubConnection] "
51389 "Creating transportLayer failed");
51390 return res;
51391 }
51392
51393 /* Load connection config into server: */
51394 UA_NodeId connectionIdent;
51395 res = UA_Server_addPubSubConnection(server, &config, &connectionIdent);
51396 if(res == UA_STATUSCODE_GOOD) {
51397 /* Configuration of all Components that belong to this connection: */
51398 res = createComponentsForConnection(server, connParams, connectionIdent,
51399 pdsCount, pdsIdent);
51400 } else {
51401 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51402 "[UA_PubSubManager_createPubSubConnection] "
51403 "Connection creation failed");
51404 }
51405
51406 return res;
51407}
51408
51409/* Function called by UA_PubSubManager_createWriterGroup to configure the messageSettings
51410 * of a writerGroup */
51411static UA_StatusCode
51412setWriterGroupEncodingType(const UA_WriterGroupDataType *writerGroupParameters,
51413 UA_WriterGroupConfig *config) {
51414 if(writerGroupParameters->messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED) {
51415 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51416 "[UA_PubSubManager_setWriterGroupEncodingType] "
51417 "getting message type information failed");
51418 return UA_STATUSCODE_BADINVALIDARGUMENT;
51419 }
51420
51421 if(writerGroupParameters->messageSettings.content.decoded.type ==
51422 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]) {
51423 config->encodingMimeType = UA_PUBSUB_ENCODING_UADP;
51424 } else if(writerGroupParameters->messageSettings.content.decoded.type ==
51425 &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE]) {
51426 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51427 "[UA_PubSubManager_setWriterGroupEncodingType] "
51428 "encoding type: JSON (not implemented!)");
51429 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51430 } else {
51431 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51432 "[UA_PubSubManager_setWriterGroupEncodingType] "
51433 "invalid message encoding type");
51434 return UA_STATUSCODE_BADINVALIDARGUMENT;
51435 }
51436
51437 return UA_STATUSCODE_GOOD;
51438}
51439
51440/* WriterGroup configuration from WriterGroup object
51441 *
51442 * @param server Server object that shall be configured
51443 * @param writerGroupParameters WriterGroup configuration
51444 * @param connectionIdent NodeId of the PubSub connection, the WriterGroup belongs to
51445 * @param pdsCount Number of published DataSets
51446 * @param pdsIdent Array of NodeIds of the published DataSets */
51447static UA_StatusCode
51448createWriterGroup(UA_Server *server,
51449 const UA_WriterGroupDataType *writerGroupParameters,
51450 UA_NodeId connectionIdent, UA_UInt32 pdsCount,
51451 const UA_NodeId *pdsIdent) {
51452 UA_WriterGroupConfig config;
51453 memset(&config, 0, sizeof(UA_WriterGroupConfig));
51454 config.name = writerGroupParameters->name;
51455 config.enabled = writerGroupParameters->enabled;
51456 config.writerGroupId = writerGroupParameters->writerGroupId;
51457 config.publishingInterval = writerGroupParameters->publishingInterval;
51458 config.keepAliveTime = writerGroupParameters->keepAliveTime;
51459 config.priority = writerGroupParameters->priority;
51460 config.securityMode = writerGroupParameters->securityMode;
51461 config.transportSettings = writerGroupParameters->transportSettings;
51462 config.messageSettings = writerGroupParameters->messageSettings;
51463 config.groupPropertiesSize = writerGroupParameters->groupPropertiesSize;
51464 if(config.groupPropertiesSize > 0)
51465 config.groupProperties = writerGroupParameters->groupProperties;
51466
51467 config.maxEncapsulatedDataSetMessageCount = 255; /* non std parameter */
51468
51469 UA_StatusCode res = setWriterGroupEncodingType(writerGroupParameters, &config);
51470 if(res != UA_STATUSCODE_GOOD) {
51471 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51472 "[UA_PubSubManager_createWriterGroup] "
51473 "Setting message settings failed");
51474 return res;
51475 }
51476
51477 /* Load config into server: */
51478 UA_NodeId writerGroupIdent;
51479 res = UA_Server_addWriterGroup(server, connectionIdent, &config, &writerGroupIdent);
51480 UA_Server_setWriterGroupOperational(server, writerGroupIdent);
51481 if(res != UA_STATUSCODE_GOOD) {
51482 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51483 "[UA_PubSubManager_createWriterGroup] "
51484 "Adding WriterGroup to server failed: 0x%x", res);
51485 return res;
51486 }
51487
51488 /* Configuration of all DataSetWriters that belong to this WriterGroup */
51489 for(size_t dsw = 0; dsw < writerGroupParameters->dataSetWritersSize; dsw++) {
51490 res = createDataSetWriter(server, &writerGroupParameters->dataSetWriters[dsw],
51491 writerGroupIdent, pdsCount, pdsIdent);
51492 if(res != UA_STATUSCODE_GOOD) {
51493 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51494 "[UA_PubSubManager_createWriterGroup] "
51495 "DataSetWriter Creation failed.");
51496 break;
51497 }
51498 }
51499 return res;
51500}
51501
51502/* Function called by UA_PubSubManager_createDataSetWriter. It searches for a
51503 * PublishedDataSet that is referenced by the DataSetWriter. If a related PDS is found,
51504 * the DSWriter will be added to the server, otherwise, no DSWriter will be added.
51505 *
51506 * @param server UA_Server object that shall be configured
51507 * @param writerGroupIdent NodeId of writerGroup, the DataSetWriter belongs to
51508 * @param dsWriterConfig WriterGroup configuration
51509 * @param pdsCount Number of published DataSets
51510 * @param pdsIdent Array of NodeIds of the published DataSets */
51511static UA_StatusCode
51512addDataSetWriterWithPdsReference(UA_Server *server, UA_NodeId writerGroupIdent,
51513 const UA_DataSetWriterConfig *dsWriterConfig,
51514 UA_UInt32 pdsCount, const UA_NodeId *pdsIdent) {
51515 UA_NodeId dataSetWriterIdent;
51516 UA_PublishedDataSetConfig pdsConfig;
51517 UA_Boolean pdsFound = false;
51518
51519 UA_StatusCode res = UA_STATUSCODE_GOOD;
51520 for(size_t pds = 0; pds < pdsCount && res == UA_STATUSCODE_GOOD; pds++) {
51521 res = UA_Server_getPublishedDataSetConfig(server, pdsIdent[pds], &pdsConfig);
51522 /* members of pdsConfig must be deleted manually */
51523 if(res != UA_STATUSCODE_GOOD) {
51524 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51525 "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
51526 "Getting pdsConfig from NodeId failed.");
51527 return res;
51528 }
51529
51530 if(dsWriterConfig->dataSetName.length == pdsConfig.name.length &&
51531 0 == strncmp((const char *)dsWriterConfig->dataSetName.data,
51532 (const char *)pdsConfig.name.data,
51533 dsWriterConfig->dataSetName.length)) {
51534 /* DSWriter will only be created, if a matching PDS is found: */
51535 res = UA_Server_addDataSetWriter(server, writerGroupIdent, pdsIdent[pds],
51536 dsWriterConfig, &dataSetWriterIdent);
51537 if(res != UA_STATUSCODE_GOOD) {
51538 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51539 "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
51540 "Adding DataSetWriter failed");
51541 } else {
51542 pdsFound = true;
51543 }
51544
51545 UA_PublishedDataSetConfig_clear(&pdsConfig);
51546 if(pdsFound)
51547 break; /* break loop if corresponding publishedDataSet was found */
51548 }
51549 }
51550
51551 if(!pdsFound) {
51552 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51553 "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
51554 "No matching DataSet found; no DataSetWriter created");
51555 }
51556
51557 return res;
51558}
51559
51560/* Creates DataSetWriter configuration from DataSetWriter object
51561 *
51562 * @param server UA_Server object that shall be configured
51563 * @param dataSetWriterParameters DataSetWriter Configuration
51564 * @param writerGroupIdent NodeId of writerGroup, the DataSetWriter belongs to
51565 * @param pdsCount Number of published DataSets
51566 * @param pdsIdent Array of NodeIds of the published DataSets */
51567static UA_StatusCode
51568createDataSetWriter(UA_Server *server,
51569 const UA_DataSetWriterDataType *dataSetWriterParameters,
51570 UA_NodeId writerGroupIdent, UA_UInt32 pdsCount,
51571 const UA_NodeId *pdsIdent) {
51572 UA_DataSetWriterConfig config;
51573 memset(&config, 0, sizeof(UA_DataSetWriterConfig));
51574 config.name = dataSetWriterParameters->name;
51575 config.dataSetWriterId = dataSetWriterParameters->dataSetWriterId;
51576 config.keyFrameCount = dataSetWriterParameters->keyFrameCount;
51577 config.dataSetFieldContentMask = dataSetWriterParameters->dataSetFieldContentMask;
51578 config.messageSettings = dataSetWriterParameters->messageSettings;
51579 config.dataSetName = dataSetWriterParameters->dataSetName;
51580 config.dataSetWriterPropertiesSize = dataSetWriterParameters->dataSetWriterPropertiesSize;
51581 if(config.dataSetWriterPropertiesSize > 0)
51582 config.dataSetWriterProperties = dataSetWriterParameters->dataSetWriterProperties;
51583
51584 UA_StatusCode res = addDataSetWriterWithPdsReference(server, writerGroupIdent,
51585 &config, pdsCount, pdsIdent);
51586 if(res != UA_STATUSCODE_GOOD) {
51587 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51588 "[UA_PubSubManager_createDataSetWriter] "
51589 "Referencing related PDS failed");
51590 }
51591
51592 return res;
51593}
51594
51595/* Creates ReaderGroup configuration from ReaderGroup object
51596 *
51597 * @param server UA_Server object that shall be configured
51598 * @param readerGroupParameters ReaderGroup configuration
51599 * @param connectionIdent NodeId of the PubSub connection, the ReaderGroup belongs to */
51600static UA_StatusCode
51601createReaderGroup(UA_Server *server,
51602 const UA_ReaderGroupDataType *readerGroupParameters,
51603 UA_NodeId connectionIdent) {
51604 UA_ReaderGroupConfig config;
51605 memset(&config, 0, sizeof(UA_ReaderGroupConfig));
51606
51607 config.name = readerGroupParameters->name;
51608 config.securityParameters.securityMode = readerGroupParameters->securityMode;
51609
51610 UA_NodeId readerGroupIdent;
51611 UA_StatusCode res =
51612 UA_Server_addReaderGroup(server, connectionIdent, &config, &readerGroupIdent);
51613 if(res != UA_STATUSCODE_GOOD) {
51614 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51615 "[UA_PubSubManager_createReaderGroup] Adding ReaderGroup "
51616 "to server failed: 0x%x", res);
51617 return res;
51618 }
51619
51620 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51621 "[UA_PubSubManager_createReaderGroup] ReaderGroup successfully added.");
51622 for(UA_UInt32 i = 0; i < readerGroupParameters->dataSetReadersSize; i++) {
51623 res = createDataSetReader(server, &readerGroupParameters->dataSetReaders[i],
51624 readerGroupIdent);
51625 if(res != UA_STATUSCODE_GOOD) {
51626 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51627 "[UA_PubSubManager_createReaderGroup] Creating DataSetReader failed");
51628 break;
51629 }
51630 }
51631
51632 if(res == UA_STATUSCODE_GOOD)
51633 UA_Server_setReaderGroupOperational(server, readerGroupIdent);
51634
51635 return res;
51636}
51637
51638/* Creates TargetVariables or SubscribedDataSetMirror for a given DataSetReader
51639 *
51640 * @param server UA_Server object that shall be configured
51641 * @param dsReaderIdent NodeId of the DataSetReader the SubscribedDataSet belongs to
51642 * @param dataSetReaderParameters Configuration Parameters of the DataSetReader */
51643static UA_StatusCode
51644addSubscribedDataSet(UA_Server *server, const UA_NodeId dsReaderIdent,
51645 const UA_ExtensionObject *subscribedDataSet) {
51646 if(subscribedDataSet->content.decoded.type ==
51647 &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]) {
51648 UA_TargetVariablesDataType *tmpTargetVars = (UA_TargetVariablesDataType*)
51649 subscribedDataSet->content.decoded.data;
51650 UA_FieldTargetVariable *targetVars = (UA_FieldTargetVariable *)
51651 UA_calloc(tmpTargetVars->targetVariablesSize, sizeof(UA_FieldTargetVariable));
51652
51653 for(size_t index = 0; index < tmpTargetVars->targetVariablesSize; index++) {
51654 UA_FieldTargetDataType_copy(&tmpTargetVars->targetVariables[index],
51655 &targetVars[index].targetVariable);
51656 }
51657
51658 UA_StatusCode res =
51659 UA_Server_DataSetReader_createTargetVariables(server, dsReaderIdent,
51660 tmpTargetVars->targetVariablesSize,
51661 targetVars);
51662 if(res != UA_STATUSCODE_GOOD) {
51663 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51664 "[UA_PubSubManager_addSubscribedDataSet] "
51665 "create TargetVariables failed");
51666 }
51667
51668 for(size_t index = 0; index < tmpTargetVars->targetVariablesSize; index++) {
51669 UA_FieldTargetDataType_clear(&targetVars[index].targetVariable);
51670 }
51671
51672 UA_free(targetVars);
51673 return res;
51674 }
51675
51676 if(subscribedDataSet->content.decoded.type ==
51677 &UA_TYPES[UA_TYPES_SUBSCRIBEDDATASETMIRRORDATATYPE]) {
51678 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51679 "[UA_PubSubManager_addSubscribedDataSet] "
51680 "DataSetMirror is currently not supported");
51681 return UA_STATUSCODE_BADINVALIDARGUMENT;
51682 }
51683
51684 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51685 "[UA_PubSubManager_addSubscribedDataSet] "
51686 "Invalid Type of SubscribedDataSet");
51687 return UA_STATUSCODE_BADINTERNALERROR;
51688}
51689
51690/* Creates DataSetReader configuration from DataSetReader object
51691 *
51692 * @param server UA_Server object that shall be configured
51693 * @param dataSetReaderParameters DataSetReader configuration
51694 * @param writerGroupIdent NodeId of readerGroupParameters, the DataSetReader belongs to */
51695static UA_StatusCode
51696createDataSetReader(UA_Server *server, const UA_DataSetReaderDataType *dsrParams,
51697 UA_NodeId readerGroupIdent) {
51698 UA_DataSetReaderConfig config;
51699 memset(&config, 0, sizeof(UA_DataSetReaderConfig));
51700
51701 config.name = dsrParams->name;
51702 config.publisherId = dsrParams->publisherId;
51703 config.writerGroupId = dsrParams->writerGroupId;
51704 config.dataSetWriterId = dsrParams->dataSetWriterId;
51705 config.dataSetMetaData = dsrParams->dataSetMetaData;
51706 config.dataSetFieldContentMask = dsrParams->dataSetFieldContentMask;
51707 config.messageReceiveTimeout = dsrParams->messageReceiveTimeout;
51708 config.messageSettings = dsrParams->messageSettings;
51709
51710 UA_NodeId dsReaderIdent;
51711 UA_StatusCode res = UA_Server_addDataSetReader(server, readerGroupIdent,
51712 &config, &dsReaderIdent);
51713 if(res == UA_STATUSCODE_GOOD)
51714 res = addSubscribedDataSet(server, dsReaderIdent,
51715 &dsrParams->subscribedDataSet);
51716 if(res != UA_STATUSCODE_GOOD) {
51717 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51718 "[UA_PubSubManager_createDataSetReader] "
51719 "create subscribedDataSet failed");
51720 }
51721
51722 return res;
51723}
51724
51725/* Determines whether PublishedDataSet is of type PublishedItems or PublishedEvents.
51726 * (PublishedEvents are currently not supported!)
51727 *
51728 * @param publishedDataSetParameters PublishedDataSet parameters
51729 * @param config PublishedDataSet configuration object */
51730static UA_StatusCode
51731setPublishedDataSetType(const UA_PublishedDataSetDataType *pdsParams,
51732 UA_PublishedDataSetConfig *config) {
51733 if(pdsParams->dataSetSource.encoding != UA_EXTENSIONOBJECT_DECODED)
51734 return UA_STATUSCODE_BADINTERNALERROR;
51735
51736 const UA_DataType *sourceType = pdsParams->dataSetSource.content.decoded.type;
51737 if(sourceType == &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]) {
51738 config->publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
51739 return UA_STATUSCODE_GOOD;
51740 } else if(sourceType == &UA_TYPES[UA_TYPES_PUBLISHEDEVENTSDATATYPE]) {
51741 /* config.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDEVENTS; */
51742 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51743 "[UA_PubSubManager_setPublishedDataSetType] Published events not supported.");
51744 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51745 }
51746
51747 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51748 "[UA_PubSubManager_setPublishedDataSetType] Invalid DataSetSourceDataType.");
51749 return UA_STATUSCODE_BADINTERNALERROR;
51750}
51751
51752/* Creates PublishedDataSetConfig object from PublishedDataSet object
51753 *
51754 * @param server UA_Server object that shall be configured
51755 * @param pdsParams publishedDataSet configuration
51756 * @param pdsIdent NodeId of the publishedDataSet */
51757static UA_StatusCode
51758createPublishedDataSet(UA_Server *server,
51759 const UA_PublishedDataSetDataType *pdsParams,
51760 UA_NodeId *pdsIdent) {
51761 UA_PublishedDataSetConfig config;
51762 memset(&config, 0, sizeof(UA_PublishedDataSetConfig));
51763
51764 config.name = pdsParams->name;
51765 UA_StatusCode res = setPublishedDataSetType(pdsParams, &config);
51766 if(res != UA_STATUSCODE_GOOD)
51767 return res;
51768
51769 res = UA_Server_addPublishedDataSet(server, &config, pdsIdent).addResult;
51770 if(res != UA_STATUSCODE_GOOD) {
51771 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51772 "[UA_PubSubManager_createPublishedDataSet] "
51773 "Adding PublishedDataSet failed.");
51774 return res;
51775 }
51776
51777 /* DataSetField configuration for this publishedDataSet: */
51778 res = createDataSetFields(server, pdsIdent, pdsParams);
51779 if(res != UA_STATUSCODE_GOOD) {
51780 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51781 "[UA_PubSubManager_createPublishedDataSet] "
51782 "Creating DataSetFieldConfig failed.");
51783 }
51784
51785 return res;
51786}
51787
51788/* Adds DataSetField Variables bound to a certain PublishedDataSet. This method does NOT
51789 * check, whether the PublishedDataSet actually contains Variables instead of Events!
51790 *
51791 * @param server UA_Server object that shall be configured
51792 * @param pdsIdent NodeId of the publishedDataSet, the DataSetField belongs to
51793 * @param publishedDataSetParameters publishedDataSet configuration */
51794static UA_StatusCode
51795addDataSetFieldVariables(UA_Server *server, const UA_NodeId *pdsIdent,
51796 const UA_PublishedDataSetDataType *pdsParams) {
51797 UA_PublishedDataItemsDataType *pdItems = (UA_PublishedDataItemsDataType *)
51798 pdsParams->dataSetSource.content.decoded.data;
51799 if(pdItems->publishedDataSize != pdsParams->dataSetMetaData.fieldsSize)
51800 return UA_STATUSCODE_BADINTERNALERROR;
51801
51802 for(size_t i = 0; i < pdItems->publishedDataSize; i++) {
51803 UA_DataSetFieldConfig fc;
51804 memset(&fc, 0, sizeof(UA_DataSetFieldConfig));
51805 fc.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
51806 fc.field.variable.configurationVersion = pdsParams->dataSetMetaData.configurationVersion;
51807 fc.field.variable.fieldNameAlias = pdsParams->dataSetMetaData.fields[i].name;
51808 fc.field.variable.promotedField = pdsParams->dataSetMetaData.
51809 fields[i].fieldFlags & 0x0001;
51810 fc.field.variable.publishParameters = pdItems->publishedData[i];
51811
51812 UA_NodeId fieldIdent;
51813 UA_StatusCode res = UA_Server_addDataSetField(server, *pdsIdent, &fc, &fieldIdent).result;
51814 if(res != UA_STATUSCODE_GOOD) {
51815 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51816 "[UA_PubSubManager_addDataSetFieldVariables] "
51817 "Adding DataSetField Variable failed.");
51818 return res;
51819 }
51820 }
51821
51822 return UA_STATUSCODE_GOOD;
51823}
51824
51825/* Checks if PublishedDataSet contains event or variable fields and calls the
51826 * corresponding method to add these fields to the server.
51827 *
51828 * @param server UA_Server object that shall be configured
51829 * @param pdsIdent NodeId of the publishedDataSet, the DataSetFields belongs to
51830 * @param pdsParams publishedDataSet configuration */
51831static UA_StatusCode
51832createDataSetFields(UA_Server *server, const UA_NodeId *pdsIdent,
51833 const UA_PublishedDataSetDataType *pdsParams) {
51834 if(pdsParams->dataSetSource.encoding != UA_EXTENSIONOBJECT_DECODED)
51835 return UA_STATUSCODE_BADINTERNALERROR;
51836
51837 if(pdsParams->dataSetSource.content.decoded.type ==
51838 &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE])
51839 return addDataSetFieldVariables(server, pdsIdent, pdsParams);
51840
51841 /* TODO: Implement Routine for adding Event DataSetFields */
51842 if(pdsParams->dataSetSource.content.decoded.type ==
51843 &UA_TYPES[UA_TYPES_PUBLISHEDEVENTSDATATYPE]) {
51844 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51845 "[UA_PubSubManager_createDataSetFields] "
51846 "Published events not supported.");
51847 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51848 }
51849
51850 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51851 "[UA_PubSubManager_createDataSetFields] "
51852 "Invalid DataSetSourceDataType.");
51853 return UA_STATUSCODE_BADINTERNALERROR;
51854}
51855
51856UA_StatusCode
51857UA_PubSubManager_loadPubSubConfigFromByteString(UA_Server *server,
51858 const UA_ByteString buffer) {
51859 size_t offset = 0;
51860 UA_ExtensionObject decodedFile;
51861 UA_StatusCode res = UA_ExtensionObject_decodeBinary(&buffer, &offset, &decodedFile);
51862 if(res != UA_STATUSCODE_GOOD) {
51863 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51864 "[UA_decodeBinFile] decoding UA_Binary failed");
51865 goto cleanup;
51866 }
51867
51868 UA_PubSubConfigurationDataType *pubSubConfig = NULL;
51869 res = extractPubSubConfigFromExtensionObject(&decodedFile, &pubSubConfig);
51870 if(res != UA_STATUSCODE_GOOD) {
51871 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51872 "[UA_PubSubManager_loadPubSubConfigFromByteString] "
51873 "Extracting PubSub Configuration failed");
51874 goto cleanup;
51875 }
51876
51877 res = updatePubSubConfig(server, pubSubConfig);
51878 if(res != UA_STATUSCODE_GOOD) {
51879 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51880 "[UA_PubSubManager_loadPubSubConfigFromByteString] "
51881 "Loading PubSub configuration into server failed");
51882 goto cleanup;
51883 }
51884
51885 cleanup:
51886 UA_ExtensionObject_clear(&decodedFile);
51887 return res;
51888}
51889
51890/* Encodes a PubSubConfigurationDataType object as ByteString using the UA Binary Data
51891 * Encoding */
51892static UA_StatusCode
51893encodePubSubConfiguration(UA_PubSubConfigurationDataType *configurationParameters,
51894 UA_ByteString *buffer) {
51895 UA_UABinaryFileDataType binFile;
51896 memset(&binFile, 0, sizeof(UA_UABinaryFileDataType));
51897 /*Perhaps, additional initializations of binFile are necessary here.*/
51898
51899 UA_Variant_setScalar(&binFile.body, configurationParameters,
51900 &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]);
51901
51902 UA_ExtensionObject container;
51903 memset(&container, 0, sizeof(UA_ExtensionObject));
51904 container.encoding = UA_EXTENSIONOBJECT_DECODED;
51905 container.content.decoded.type = &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE];
51906 container.content.decoded.data = &binFile;
51907
51908 size_t fileSize = UA_ExtensionObject_calcSizeBinary(&container);
51909 buffer->data = (UA_Byte*)UA_calloc(fileSize, sizeof(UA_Byte));
51910 if(buffer->data == NULL) {
51911 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51912 "[UA_PubSubManager_encodePubSubConfiguration] Allocating buffer failed");
51913 return UA_STATUSCODE_BADOUTOFMEMORY;
51914 }
51915
51916 buffer->length = fileSize;
51917
51918 UA_Byte *bufferPos = buffer->data;
51919 UA_StatusCode res =
51920 UA_ExtensionObject_encodeBinary(&container, &bufferPos, bufferPos + fileSize);
51921 if(res != UA_STATUSCODE_GOOD) {
51922 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51923 "[UA_PubSubManager_encodePubSubConfiguration] Encoding failed");
51924 }
51925 return res;
51926}
51927
51928static UA_StatusCode
51929generatePublishedDataSetDataType(const UA_PublishedDataSet *src,
51930 UA_PublishedDataSetDataType *dst) {
51931 if(src->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS)
51932 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51933
51934 memset(dst, 0, sizeof(UA_PublishedDataSetDataType));
51935
51936 UA_PublishedDataItemsDataType *tmp = UA_PublishedDataItemsDataType_new();
51937 UA_String_copy(&src->config.name, &dst->name);
51938 dst->dataSetMetaData.fieldsSize = src->fieldSize;
51939
51940 size_t index = 0;
51941 tmp->publishedDataSize = src->fieldSize;
51942 tmp->publishedData = (UA_PublishedVariableDataType*)
51943 UA_Array_new(tmp->publishedDataSize, &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]);
51944 if(tmp->publishedData == NULL) {
51945 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Allocation memory failed");
51946 return UA_STATUSCODE_BADOUTOFMEMORY;
51947 }
51948
51949 dst->dataSetMetaData.fields = (UA_FieldMetaData*)
51950 UA_Array_new(dst->dataSetMetaData.fieldsSize, &UA_TYPES[UA_TYPES_FIELDMETADATA]);
51951 if(dst->dataSetMetaData.fields == NULL) {
51952 UA_free(tmp->publishedData);
51953 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Allocation memory failed");
51954 return UA_STATUSCODE_BADOUTOFMEMORY;
51955 }
51956
51957 UA_DataSetField *dsf, *dsf_tmp = NULL;
51958 TAILQ_FOREACH_SAFE(dsf ,&src->fields, listEntry, dsf_tmp) {
51959 UA_String_copy(&dsf->config.field.variable.fieldNameAlias,
51960 &dst->dataSetMetaData.fields[index].name);
51961 UA_PublishedVariableDataType_copy(&dsf->config.field.variable.publishParameters,
51962 &tmp->publishedData[index]);
51963 UA_ConfigurationVersionDataType_copy(&dsf->config.field.variable.configurationVersion,
51964 &dst->dataSetMetaData.configurationVersion);
51965 dst->dataSetMetaData.fields[index].fieldFlags =
51966 dsf->config.field.variable.promotedField;
51967 index++;
51968 }
51969 UA_ExtensionObject_setValue(&dst->dataSetSource, tmp,
51970 &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]);
51971
51972 return UA_STATUSCODE_GOOD;
51973}
51974
51975static UA_StatusCode
51976generateDataSetWriterDataType(const UA_DataSetWriter *src,
51977 UA_DataSetWriterDataType *dst) {
51978 memset(dst, 0, sizeof(UA_DataSetWriterDataType));
51979
51980 UA_String_copy(&src->config.name, &dst->name);
51981 dst->dataSetWriterId = src->config.dataSetWriterId;
51982 dst->keyFrameCount = src->config.keyFrameCount;
51983 dst->dataSetFieldContentMask = src->config.dataSetFieldContentMask;
51984 UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
51985 UA_String_copy(&src->config.dataSetName, &dst->dataSetName);
51986
51987 dst->dataSetWriterPropertiesSize = src->config.dataSetWriterPropertiesSize;
51988 for(size_t i = 0; i < src->config.dataSetWriterPropertiesSize; i++) {
51989 UA_KeyValuePair_copy(&src->config.dataSetWriterProperties[i],
51990 &dst->dataSetWriterProperties[i]);
51991 }
51992
51993 return UA_STATUSCODE_GOOD;
51994}
51995
51996static UA_StatusCode
51997generateWriterGroupDataType(const UA_WriterGroup *src,
51998 UA_WriterGroupDataType *dst) {
51999 memset(dst, 0, sizeof(UA_WriterGroupDataType));
52000
52001 UA_String_copy(&src->config.name, &dst->name);
52002 dst->enabled = src->config.enabled;
52003 dst->writerGroupId = src->config.writerGroupId;
52004 dst->publishingInterval = src->config.publishingInterval;
52005 dst->keepAliveTime = src->config.keepAliveTime;
52006 dst->priority = src->config.priority;
52007 dst->securityMode = src->config.securityMode;
52008
52009 UA_ExtensionObject_copy(&src->config.transportSettings, &dst->transportSettings);
52010 UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
52011
52012 dst->groupPropertiesSize = src->config.groupPropertiesSize;
52013 dst->groupProperties = (UA_KeyValuePair*)
52014 UA_Array_new(dst->groupPropertiesSize, &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
52015 for(size_t index = 0; index < dst->groupPropertiesSize; index++) {
52016 UA_KeyValuePair_copy(&src->config.groupProperties[index],
52017 &dst->groupProperties[index]);
52018 }
52019
52020 dst->dataSetWriters = (UA_DataSetWriterDataType*)
52021 UA_calloc(src->writersCount, sizeof(UA_DataSetWriterDataType));
52022 if(!dst->dataSetWriters)
52023 return UA_STATUSCODE_BADOUTOFMEMORY;
52024
52025 dst->dataSetWritersSize = src->writersCount;
52026
52027 UA_DataSetWriter *dsw;
52028 size_t dsWriterIndex = 0;
52029 LIST_FOREACH(dsw, &src->writers, listEntry) {
52030 UA_StatusCode res =
52031 generateDataSetWriterDataType(dsw, &dst->dataSetWriters[dsWriterIndex]);
52032 if(res != UA_STATUSCODE_GOOD)
52033 return res;
52034 dsWriterIndex++;
52035 }
52036
52037 return UA_STATUSCODE_GOOD;
52038}
52039
52040static UA_StatusCode
52041generateDataSetReaderDataType(const UA_DataSetReader *src,
52042 UA_DataSetReaderDataType *dst) {
52043 UA_StatusCode res = UA_STATUSCODE_GOOD;
52044 memset(dst, 0, sizeof(UA_DataSetReaderDataType));
52045 dst->writerGroupId = src->config.writerGroupId;
52046 dst->dataSetWriterId = src->config.dataSetWriterId;
52047 dst->dataSetFieldContentMask = src->config.dataSetFieldContentMask;
52048 dst->messageReceiveTimeout = src->config.messageReceiveTimeout;
52049 res |= UA_String_copy(&src->config.name, &dst->name);
52050 res |= UA_Variant_copy(&src->config.publisherId, &dst->publisherId);
52051 res |= UA_DataSetMetaDataType_copy(&src->config.dataSetMetaData,
52052 &dst->dataSetMetaData);
52053 res |= UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
52054
52055 UA_TargetVariablesDataType *tmpTarget = UA_TargetVariablesDataType_new();
52056 if(!tmpTarget)
52057 return UA_STATUSCODE_BADOUTOFMEMORY;
52058 UA_ExtensionObject_setValue(&dst->subscribedDataSet, tmpTarget,
52059 &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]);
52060
52061 const UA_TargetVariables *targets =
52062 &src->config.subscribedDataSet.subscribedDataSetTarget;
52063 tmpTarget->targetVariables = (UA_FieldTargetDataType *)
52064 UA_calloc(targets->targetVariablesSize, sizeof(UA_FieldTargetDataType));
52065 if(!tmpTarget->targetVariables)
52066 return UA_STATUSCODE_BADOUTOFMEMORY;
52067 tmpTarget->targetVariablesSize = targets->targetVariablesSize;
52068
52069 for(size_t i = 0; i < tmpTarget->targetVariablesSize; i++) {
52070 res |= UA_FieldTargetDataType_copy(&targets->targetVariables[i].targetVariable,
52071 &tmpTarget->targetVariables[i]);
52072 }
52073
52074 return res;
52075}
52076
52077static UA_StatusCode
52078generateReaderGroupDataType(const UA_ReaderGroup *src,
52079 UA_ReaderGroupDataType *dst) {
52080 memset(dst, 0, sizeof(UA_ReaderGroupDataType));
52081
52082 UA_String_copy(&src->config.name, &dst->name);
52083 dst->dataSetReaders = (UA_DataSetReaderDataType*)
52084 UA_calloc(src->readersCount, sizeof(UA_DataSetReaderDataType));
52085 if(dst->dataSetReaders == NULL)
52086 return UA_STATUSCODE_BADOUTOFMEMORY;
52087 dst->dataSetReadersSize = src->readersCount;
52088
52089 size_t i = 0;
52090 UA_DataSetReader *dsr, *dsr_tmp = NULL;
52091 LIST_FOREACH_SAFE(dsr, &src->readers, listEntry, dsr_tmp) {
52092 UA_StatusCode res =
52093 generateDataSetReaderDataType(dsr, &dst->dataSetReaders[i]);
52094 if(res != UA_STATUSCODE_GOOD)
52095 return res;
52096 i++;
52097 }
52098
52099 return UA_STATUSCODE_GOOD;
52100}
52101
52102/* Generates a PubSubConnectionDataType object from a PubSubConnection. */
52103static UA_StatusCode
52104generatePubSubConnectionDataType(const UA_PubSubConnection *src,
52105 UA_PubSubConnectionDataType *dst) {
52106 memset(dst, 0, sizeof(UA_PubSubConnectionDataType));
52107
52108 UA_String_copy(&src->config->name, &dst->name);
52109 UA_String_copy(&src->config->transportProfileUri, &dst->transportProfileUri);
52110 dst->enabled = src->config->enabled;
52111
52112 dst->connectionPropertiesSize = src->config->connectionPropertiesSize;
52113 for(size_t i = 0; i < src->config->connectionPropertiesSize; i++) {
52114 UA_KeyValuePair_copy(&src->config->connectionProperties[i],
52115 &dst->connectionProperties[i]);
52116 }
52117
52118 if(src->config->publisherIdType == UA_PUBSUB_PUBLISHERID_NUMERIC) {
52119 UA_Variant_setScalarCopy(&dst->publisherId,
52120 &src->config->publisherId.numeric,
52121 &UA_TYPES[UA_TYPES_UINT32]);
52122 } else if(src->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING) {
52123 UA_Variant_setScalarCopy(&dst->publisherId,
52124 &src->config->publisherId.string,
52125 &UA_TYPES[UA_TYPES_STRING]);
52126 }
52127
52128 /* Possibly, array size and dimensions of src->config->address and
52129 * src->config->connectionTransportSettings should be checked beforehand. */
52130 dst->address.encoding = UA_EXTENSIONOBJECT_DECODED;
52131 dst->address.content.decoded.type = src->config->address.type;
52132 UA_StatusCode res =
52133 UA_Array_copy(src->config->address.data, 1,
52134 &dst->address.content.decoded.data, src->config->address.type);
52135 if(res != UA_STATUSCODE_GOOD)
52136 return res;
52137
52138 if(src->config->connectionTransportSettings.data) {
52139 dst->transportSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
52140 dst->transportSettings.content.decoded.type =
52141 src->config->connectionTransportSettings.type;
52142 res = UA_Array_copy(src->config->connectionTransportSettings.data, 1,
52143 &dst->transportSettings.content.decoded.data,
52144 src->config->connectionTransportSettings.type);
52145
52146 if(res != UA_STATUSCODE_GOOD)
52147 return res;
52148 }
52149
52150 dst->writerGroups = (UA_WriterGroupDataType*)
52151 UA_calloc(src->writerGroupsSize, sizeof(UA_WriterGroupDataType));
52152 if(dst->writerGroups == NULL) {
52153 return UA_STATUSCODE_BADOUTOFMEMORY;
52154 }
52155
52156 dst->writerGroupsSize = src->writerGroupsSize;
52157 UA_WriterGroup *wg, *wg_tmp = NULL;
52158 size_t wgIndex = 0;
52159 LIST_FOREACH_SAFE(wg ,&src->writerGroups, listEntry, wg_tmp) {
52160 res = generateWriterGroupDataType(wg, &dst->writerGroups[wgIndex]);
52161 if(res != UA_STATUSCODE_GOOD)
52162 return res;
52163 wgIndex++;
52164 }
52165
52166 dst->readerGroups = (UA_ReaderGroupDataType*)
52167 UA_calloc(src->readerGroupsSize, sizeof(UA_ReaderGroupDataType));
52168 if(dst->readerGroups == NULL) {
52169 return UA_STATUSCODE_BADOUTOFMEMORY;
52170 }
52171
52172 dst->readerGroupsSize = src->readerGroupsSize;
52173 UA_ReaderGroup *rg = NULL;
52174 size_t rgIndex = 0;
52175 LIST_FOREACH(rg, &src->readerGroups, listEntry) {
52176 res = generateReaderGroupDataType(rg, &dst->readerGroups[rgIndex]);
52177 if(res != UA_STATUSCODE_GOOD)
52178 return res;
52179 rgIndex++;
52180 }
52181
52182 return UA_STATUSCODE_GOOD;
52183}
52184
52185UA_StatusCode
52186generatePubSubConfigurationDataType(const UA_Server* server,
52187 UA_PubSubConfigurationDataType *configDT) {
52188 UA_StatusCode res = UA_STATUSCODE_GOOD;
52189 const UA_PubSubManager *manager = &server->pubSubManager;
52190 memset(configDT, 0, sizeof(UA_PubSubConfigurationDataType));
52191
52192 configDT->publishedDataSets = (UA_PublishedDataSetDataType*)
52193 UA_calloc(manager->publishedDataSetsSize,
52194 sizeof(UA_PublishedDataSetDataType));
52195 if(configDT->publishedDataSets == NULL)
52196 return UA_STATUSCODE_BADOUTOFMEMORY;
52197 configDT->publishedDataSetsSize = manager->publishedDataSetsSize;
52198
52199 UA_PublishedDataSet *pds;
52200 UA_UInt32 pdsIndex = 0;
52201 TAILQ_FOREACH(pds, &manager->publishedDataSets, listEntry) {
52202 UA_PublishedDataSetDataType *dst = &configDT->publishedDataSets[pdsIndex];
52203 res = generatePublishedDataSetDataType(pds, dst);
52204 if(res != UA_STATUSCODE_GOOD) {
52205 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52206 "[UA_PubSubManager_generatePubSubConfigurationDataType] "
52207 "retrieving PublishedDataSet configuration failed");
52208 return res;
52209 }
52210 pdsIndex++;
52211 }
52212
52213 configDT->connections = (UA_PubSubConnectionDataType*)
52214 UA_calloc(manager->connectionsSize, sizeof(UA_PubSubConnectionDataType));
52215 if(configDT->connections == NULL)
52216 return UA_STATUSCODE_BADOUTOFMEMORY;
52217 configDT->connectionsSize = manager->connectionsSize;
52218
52219 UA_UInt32 connectionIndex = 0;
52220 UA_PubSubConnection *connection;
52221 TAILQ_FOREACH(connection, &manager->connections, listEntry) {
52222 UA_PubSubConnectionDataType *cdt = &configDT->connections[connectionIndex];
52223 res = generatePubSubConnectionDataType(connection, cdt);
52224 if(res != UA_STATUSCODE_GOOD) {
52225 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52226 "[UA_PubSubManager_generatePubSubConfigurationDataType] "
52227 "retrieving PubSubConnection configuration failed");
52228 return res;
52229 }
52230 connectionIndex++;
52231 }
52232
52233 return UA_STATUSCODE_GOOD;
52234}
52235
52236UA_StatusCode
52237UA_PubSubManager_getEncodedPubSubConfiguration(UA_Server *server,
52238 UA_ByteString *buffer) {
52239 UA_PubSubConfigurationDataType config;
52240 memset(&config, 0, sizeof(UA_PubSubConfigurationDataType));
52241
52242 UA_StatusCode res = generatePubSubConfigurationDataType(server, &config);
52243 if(res != UA_STATUSCODE_GOOD) {
52244 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52245 "retrieving PubSub configuration from server failed");
52246 goto cleanup;
52247 }
52248
52249 res = encodePubSubConfiguration(&config, buffer);
52250 if(res != UA_STATUSCODE_GOOD) {
52251 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52252 "encoding PubSub configuration failed");
52253 goto cleanup;
52254 }
52255
52256 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52257 "Saving PubSub config was successful");
52258
52259 cleanup:
52260 UA_PubSubConfigurationDataType_clear(&config);
52261 return res;
52262}
52263
52264#endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */
52265
52266/**** amalgamated original file "/build/src_generated/open62541/namespace0_generated.c" ****/
52267
52268/* WARNING: This is a generated file.
52269 * Any manual changes will be overwritten. */
52270
52271
52272
52273/* HasAddIn - ns=0;i=17604 */
52274
52275static UA_StatusCode function_namespace0_generated_0_begin(UA_Server *server, UA_UInt16* ns) {
52276UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52277UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52278attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "AddInOf");
52279attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasAddIn");
52280retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52281requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17604LU),
52282parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52283referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52284browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasAddIn"),
52285 typeDefinition: UA_NODEID_NULL,
52286attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52287return retVal;
52288}
52289
52290static UA_StatusCode function_namespace0_generated_0_finish(UA_Server *server, UA_UInt16* ns) {
52291return UA_Server_addNode_finish(server,
52292nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17604LU)
52293);
52294}
52295
52296/* HasHistoricalConfiguration - ns=0;i=56 */
52297
52298static UA_StatusCode function_namespace0_generated_1_begin(UA_Server *server, UA_UInt16* ns) {
52299UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52300UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52301attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "HistoricalConfigurationOf");
52302attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasHistoricalConfiguration");
52303retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52304requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 56LU),
52305parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 44LU),
52306referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52307browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasHistoricalConfiguration"),
52308 typeDefinition: UA_NODEID_NULL,
52309attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52310return retVal;
52311}
52312
52313static UA_StatusCode function_namespace0_generated_1_finish(UA_Server *server, UA_UInt16* ns) {
52314return UA_Server_addNode_finish(server,
52315nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 56LU)
52316);
52317}
52318
52319/* HasEffect - ns=0;i=54 */
52320
52321static UA_StatusCode function_namespace0_generated_2_begin(UA_Server *server, UA_UInt16* ns) {
52322UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52323UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52324attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "MayBeEffectedBy");
52325attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasEffect");
52326retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52327requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 54LU),
52328parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52329referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52330browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasEffect"),
52331 typeDefinition: UA_NODEID_NULL,
52332attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52333return retVal;
52334}
52335
52336static UA_StatusCode function_namespace0_generated_2_finish(UA_Server *server, UA_UInt16* ns) {
52337return UA_Server_addNode_finish(server,
52338nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 54LU)
52339);
52340}
52341
52342/* HasCause - ns=0;i=53 */
52343
52344static UA_StatusCode function_namespace0_generated_3_begin(UA_Server *server, UA_UInt16* ns) {
52345UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52346UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52347attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "MayBeCausedBy");
52348attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasCause");
52349retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52350requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 53LU),
52351parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52352referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52353browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasCause"),
52354 typeDefinition: UA_NODEID_NULL,
52355attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52356return retVal;
52357}
52358
52359static UA_StatusCode function_namespace0_generated_3_finish(UA_Server *server, UA_UInt16* ns) {
52360return UA_Server_addNode_finish(server,
52361nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 53LU)
52362);
52363}
52364
52365/* ToState - ns=0;i=52 */
52366
52367static UA_StatusCode function_namespace0_generated_4_begin(UA_Server *server, UA_UInt16* ns) {
52368UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52369UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52370attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "FromTransition");
52371attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ToState");
52372retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52373requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 52LU),
52374parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52375referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52376browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ToState"),
52377 typeDefinition: UA_NODEID_NULL,
52378attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52379return retVal;
52380}
52381
52382static UA_StatusCode function_namespace0_generated_4_finish(UA_Server *server, UA_UInt16* ns) {
52383return UA_Server_addNode_finish(server,
52384nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 52LU)
52385);
52386}
52387
52388/* FromState - ns=0;i=51 */
52389
52390static UA_StatusCode function_namespace0_generated_5_begin(UA_Server *server, UA_UInt16* ns) {
52391UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52392UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52393attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "ToTransition");
52394attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FromState");
52395retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52396requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 51LU),
52397parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52398referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52399browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FromState"),
52400 typeDefinition: UA_NODEID_NULL,
52401attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52402return retVal;
52403}
52404
52405static UA_StatusCode function_namespace0_generated_5_finish(UA_Server *server, UA_UInt16* ns) {
52406return UA_Server_addNode_finish(server,
52407nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 51LU)
52408);
52409}
52410
52411/* DiagnosticInfo - ns=0;i=25 */
52412
52413static UA_StatusCode function_namespace0_generated_6_begin(UA_Server *server, UA_UInt16* ns) {
52414UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52415UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52416attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DiagnosticInfo");
52417retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52418requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25LU),
52419parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52420referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52421browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DiagnosticInfo"),
52422 typeDefinition: UA_NODEID_NULL,
52423attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52424return retVal;
52425}
52426
52427static UA_StatusCode function_namespace0_generated_6_finish(UA_Server *server, UA_UInt16* ns) {
52428return UA_Server_addNode_finish(server,
52429nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25LU)
52430);
52431}
52432
52433/* DataValue - ns=0;i=23 */
52434
52435static UA_StatusCode function_namespace0_generated_7_begin(UA_Server *server, UA_UInt16* ns) {
52436UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52437UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52438attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataValue");
52439retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52440requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23LU),
52441parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52442referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52443browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataValue"),
52444 typeDefinition: UA_NODEID_NULL,
52445attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52446return retVal;
52447}
52448
52449static UA_StatusCode function_namespace0_generated_7_finish(UA_Server *server, UA_UInt16* ns) {
52450return UA_Server_addNode_finish(server,
52451nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23LU)
52452);
52453}
52454
52455/* Structure - ns=0;i=22 */
52456
52457static UA_StatusCode function_namespace0_generated_8_begin(UA_Server *server, UA_UInt16* ns) {
52458UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52459UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52460attr.isAbstract = true;
52461attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Structure");
52462retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52463requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52464parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52465referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52466browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Structure"),
52467 typeDefinition: UA_NODEID_NULL,
52468attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52469return retVal;
52470}
52471
52472static UA_StatusCode function_namespace0_generated_8_finish(UA_Server *server, UA_UInt16* ns) {
52473return UA_Server_addNode_finish(server,
52474nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU)
52475);
52476}
52477
52478/* TimeZoneDataType - ns=0;i=8912 */
52479
52480static UA_StatusCode function_namespace0_generated_9_begin(UA_Server *server, UA_UInt16* ns) {
52481UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52482UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52483attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TimeZoneDataType");
52484retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52485requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU),
52486parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52487referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52488browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TimeZoneDataType"),
52489 typeDefinition: UA_NODEID_NULL,
52490attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52491return retVal;
52492}
52493
52494static UA_StatusCode function_namespace0_generated_9_finish(UA_Server *server, UA_UInt16* ns) {
52495return UA_Server_addNode_finish(server,
52496nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU)
52497);
52498}
52499
52500/* EUInformation - ns=0;i=887 */
52501
52502static UA_StatusCode function_namespace0_generated_10_begin(UA_Server *server, UA_UInt16* ns) {
52503UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52504UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52505attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EUInformation");
52506retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52507requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU),
52508parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52509referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52510browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EUInformation"),
52511 typeDefinition: UA_NODEID_NULL,
52512attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52513return retVal;
52514}
52515
52516static UA_StatusCode function_namespace0_generated_10_finish(UA_Server *server, UA_UInt16* ns) {
52517return UA_Server_addNode_finish(server,
52518nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU)
52519);
52520}
52521
52522/* Range - ns=0;i=884 */
52523
52524static UA_StatusCode function_namespace0_generated_11_begin(UA_Server *server, UA_UInt16* ns) {
52525UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52526UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52527attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Range");
52528retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52529requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU),
52530parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52531referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52532browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Range"),
52533 typeDefinition: UA_NODEID_NULL,
52534attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52535return retVal;
52536}
52537
52538static UA_StatusCode function_namespace0_generated_11_finish(UA_Server *server, UA_UInt16* ns) {
52539return UA_Server_addNode_finish(server,
52540nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU)
52541);
52542}
52543
52544/* ServerStatusDataType - ns=0;i=862 */
52545
52546static UA_StatusCode function_namespace0_generated_12_begin(UA_Server *server, UA_UInt16* ns) {
52547UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52548UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52549attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatusDataType");
52550retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52551requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU),
52552parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52553referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52554browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatusDataType"),
52555 typeDefinition: UA_NODEID_NULL,
52556attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52557return retVal;
52558}
52559
52560static UA_StatusCode function_namespace0_generated_12_finish(UA_Server *server, UA_UInt16* ns) {
52561return UA_Server_addNode_finish(server,
52562nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU)
52563);
52564}
52565
52566/* EnumValueType - ns=0;i=7594 */
52567
52568static UA_StatusCode function_namespace0_generated_13_begin(UA_Server *server, UA_UInt16* ns) {
52569UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52570UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52571attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValueType");
52572retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52573requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU),
52574parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52575referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52576browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValueType"),
52577 typeDefinition: UA_NODEID_NULL,
52578attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52579return retVal;
52580}
52581
52582static UA_StatusCode function_namespace0_generated_13_finish(UA_Server *server, UA_UInt16* ns) {
52583return UA_Server_addNode_finish(server,
52584nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU)
52585);
52586}
52587
52588/* SignedSoftwareCertificate - ns=0;i=344 */
52589
52590static UA_StatusCode function_namespace0_generated_14_begin(UA_Server *server, UA_UInt16* ns) {
52591UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52592UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52593attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SignedSoftwareCertificate");
52594retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52595requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU),
52596parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52597referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52598browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SignedSoftwareCertificate"),
52599 typeDefinition: UA_NODEID_NULL,
52600attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52601return retVal;
52602}
52603
52604static UA_StatusCode function_namespace0_generated_14_finish(UA_Server *server, UA_UInt16* ns) {
52605return UA_Server_addNode_finish(server,
52606nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU)
52607);
52608}
52609
52610/* BuildInfo - ns=0;i=338 */
52611
52612static UA_StatusCode function_namespace0_generated_15_begin(UA_Server *server, UA_UInt16* ns) {
52613UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52614UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52615attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfo");
52616retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52617requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU),
52618parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52619referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52620browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfo"),
52621 typeDefinition: UA_NODEID_NULL,
52622attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52623return retVal;
52624}
52625
52626static UA_StatusCode function_namespace0_generated_15_finish(UA_Server *server, UA_UInt16* ns) {
52627return UA_Server_addNode_finish(server,
52628nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU)
52629);
52630}
52631
52632/* Argument - ns=0;i=296 */
52633
52634static UA_StatusCode function_namespace0_generated_16_begin(UA_Server *server, UA_UInt16* ns) {
52635UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52636UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52637attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Argument");
52638retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52639requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU),
52640parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52641referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52642browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Argument"),
52643 typeDefinition: UA_NODEID_NULL,
52644attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52645return retVal;
52646}
52647
52648static UA_StatusCode function_namespace0_generated_16_finish(UA_Server *server, UA_UInt16* ns) {
52649return UA_Server_addNode_finish(server,
52650nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU)
52651);
52652}
52653
52654/* Union - ns=0;i=12756 */
52655
52656static UA_StatusCode function_namespace0_generated_17_begin(UA_Server *server, UA_UInt16* ns) {
52657UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52658UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52659attr.isAbstract = true;
52660attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Union");
52661retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52662requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12756LU),
52663parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52664referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52665browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Union"),
52666 typeDefinition: UA_NODEID_NULL,
52667attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52668return retVal;
52669}
52670
52671static UA_StatusCode function_namespace0_generated_17_finish(UA_Server *server, UA_UInt16* ns) {
52672return UA_Server_addNode_finish(server,
52673nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12756LU)
52674);
52675}
52676
52677/* LocalizedText - ns=0;i=21 */
52678
52679static UA_StatusCode function_namespace0_generated_18_begin(UA_Server *server, UA_UInt16* ns) {
52680UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52681UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52682attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocalizedText");
52683retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52684requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU),
52685parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52686referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52687browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocalizedText"),
52688 typeDefinition: UA_NODEID_NULL,
52689attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52690return retVal;
52691}
52692
52693static UA_StatusCode function_namespace0_generated_18_finish(UA_Server *server, UA_UInt16* ns) {
52694return UA_Server_addNode_finish(server,
52695nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU)
52696);
52697}
52698
52699/* QualifiedName - ns=0;i=20 */
52700
52701static UA_StatusCode function_namespace0_generated_19_begin(UA_Server *server, UA_UInt16* ns) {
52702UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52703UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52704attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QualifiedName");
52705retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52706requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20LU),
52707parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52708referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52709browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QualifiedName"),
52710 typeDefinition: UA_NODEID_NULL,
52711attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52712return retVal;
52713}
52714
52715static UA_StatusCode function_namespace0_generated_19_finish(UA_Server *server, UA_UInt16* ns) {
52716return UA_Server_addNode_finish(server,
52717nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20LU)
52718);
52719}
52720
52721/* StatusCode - ns=0;i=19 */
52722
52723static UA_StatusCode function_namespace0_generated_20_begin(UA_Server *server, UA_UInt16* ns) {
52724UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52725UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52726attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "StatusCode");
52727retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52728requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU),
52729parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52730referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52731browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "StatusCode"),
52732 typeDefinition: UA_NODEID_NULL,
52733attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52734return retVal;
52735}
52736
52737static UA_StatusCode function_namespace0_generated_20_finish(UA_Server *server, UA_UInt16* ns) {
52738return UA_Server_addNode_finish(server,
52739nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU)
52740);
52741}
52742
52743/* ExpandedNodeId - ns=0;i=18 */
52744
52745static UA_StatusCode function_namespace0_generated_21_begin(UA_Server *server, UA_UInt16* ns) {
52746UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52747UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52748attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ExpandedNodeId");
52749retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52750requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 18LU),
52751parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52752referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52753browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ExpandedNodeId"),
52754 typeDefinition: UA_NODEID_NULL,
52755attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52756return retVal;
52757}
52758
52759static UA_StatusCode function_namespace0_generated_21_finish(UA_Server *server, UA_UInt16* ns) {
52760return UA_Server_addNode_finish(server,
52761nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 18LU)
52762);
52763}
52764
52765/* NodeId - ns=0;i=17 */
52766
52767static UA_StatusCode function_namespace0_generated_22_begin(UA_Server *server, UA_UInt16* ns) {
52768UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52769UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52770attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NodeId");
52771retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52772requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU),
52773parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52774referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52775browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NodeId"),
52776 typeDefinition: UA_NODEID_NULL,
52777attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52778return retVal;
52779}
52780
52781static UA_StatusCode function_namespace0_generated_22_finish(UA_Server *server, UA_UInt16* ns) {
52782return UA_Server_addNode_finish(server,
52783nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU)
52784);
52785}
52786
52787/* XmlElement - ns=0;i=16 */
52788
52789static UA_StatusCode function_namespace0_generated_23_begin(UA_Server *server, UA_UInt16* ns) {
52790UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52791UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52792attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "XmlElement");
52793retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52794requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16LU),
52795parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52796referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52797browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "XmlElement"),
52798 typeDefinition: UA_NODEID_NULL,
52799attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52800return retVal;
52801}
52802
52803static UA_StatusCode function_namespace0_generated_23_finish(UA_Server *server, UA_UInt16* ns) {
52804return UA_Server_addNode_finish(server,
52805nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16LU)
52806);
52807}
52808
52809/* ByteString - ns=0;i=15 */
52810
52811static UA_StatusCode function_namespace0_generated_24_begin(UA_Server *server, UA_UInt16* ns) {
52812UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52813UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52814attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ByteString");
52815retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52816requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU),
52817parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52818referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52819browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ByteString"),
52820 typeDefinition: UA_NODEID_NULL,
52821attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52822return retVal;
52823}
52824
52825static UA_StatusCode function_namespace0_generated_24_finish(UA_Server *server, UA_UInt16* ns) {
52826return UA_Server_addNode_finish(server,
52827nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU)
52828);
52829}
52830
52831/* Image - ns=0;i=30 */
52832
52833static UA_StatusCode function_namespace0_generated_25_begin(UA_Server *server, UA_UInt16* ns) {
52834UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52835UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52836attr.isAbstract = true;
52837attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Image");
52838retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52839requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 30LU),
52840parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU),
52841referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52842browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Image"),
52843 typeDefinition: UA_NODEID_NULL,
52844attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52845return retVal;
52846}
52847
52848static UA_StatusCode function_namespace0_generated_25_finish(UA_Server *server, UA_UInt16* ns) {
52849return UA_Server_addNode_finish(server,
52850nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 30LU)
52851);
52852}
52853
52854/* Guid - ns=0;i=14 */
52855
52856static UA_StatusCode function_namespace0_generated_26_begin(UA_Server *server, UA_UInt16* ns) {
52857UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52858UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52859attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Guid");
52860retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52861requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14LU),
52862parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52863referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52864browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Guid"),
52865 typeDefinition: UA_NODEID_NULL,
52866attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52867return retVal;
52868}
52869
52870static UA_StatusCode function_namespace0_generated_26_finish(UA_Server *server, UA_UInt16* ns) {
52871return UA_Server_addNode_finish(server,
52872nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14LU)
52873);
52874}
52875
52876/* DateTime - ns=0;i=13 */
52877
52878static UA_StatusCode function_namespace0_generated_27_begin(UA_Server *server, UA_UInt16* ns) {
52879UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52880UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52881attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DateTime");
52882retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52883requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU),
52884parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52885referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52886browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DateTime"),
52887 typeDefinition: UA_NODEID_NULL,
52888attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52889return retVal;
52890}
52891
52892static UA_StatusCode function_namespace0_generated_27_finish(UA_Server *server, UA_UInt16* ns) {
52893return UA_Server_addNode_finish(server,
52894nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU)
52895);
52896}
52897
52898/* UtcTime - ns=0;i=294 */
52899
52900static UA_StatusCode function_namespace0_generated_28_begin(UA_Server *server, UA_UInt16* ns) {
52901UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52902UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52903attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UtcTime");
52904retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52905requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU),
52906parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU),
52907referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52908browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UtcTime"),
52909 typeDefinition: UA_NODEID_NULL,
52910attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52911return retVal;
52912}
52913
52914static UA_StatusCode function_namespace0_generated_28_finish(UA_Server *server, UA_UInt16* ns) {
52915return UA_Server_addNode_finish(server,
52916nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU)
52917);
52918}
52919
52920/* String - ns=0;i=12 */
52921
52922static UA_StatusCode function_namespace0_generated_29_begin(UA_Server *server, UA_UInt16* ns) {
52923UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52924UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52925attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "String");
52926retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52927requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU),
52928parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52929referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52930browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "String"),
52931 typeDefinition: UA_NODEID_NULL,
52932attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52933return retVal;
52934}
52935
52936static UA_StatusCode function_namespace0_generated_29_finish(UA_Server *server, UA_UInt16* ns) {
52937return UA_Server_addNode_finish(server,
52938nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU)
52939);
52940}
52941
52942/* LocaleId - ns=0;i=295 */
52943
52944static UA_StatusCode function_namespace0_generated_30_begin(UA_Server *server, UA_UInt16* ns) {
52945UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52946UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52947attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleId");
52948retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52949requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU),
52950parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU),
52951referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52952browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleId"),
52953 typeDefinition: UA_NODEID_NULL,
52954attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52955return retVal;
52956}
52957
52958static UA_StatusCode function_namespace0_generated_30_finish(UA_Server *server, UA_UInt16* ns) {
52959return UA_Server_addNode_finish(server,
52960nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU)
52961);
52962}
52963
52964/* Boolean - ns=0;i=1 */
52965
52966static UA_StatusCode function_namespace0_generated_31_begin(UA_Server *server, UA_UInt16* ns) {
52967UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52968UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52969attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Boolean");
52970retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52971requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU),
52972parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52973referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52974browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Boolean"),
52975 typeDefinition: UA_NODEID_NULL,
52976attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52977return retVal;
52978}
52979
52980static UA_StatusCode function_namespace0_generated_31_finish(UA_Server *server, UA_UInt16* ns) {
52981return UA_Server_addNode_finish(server,
52982nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU)
52983);
52984}
52985
52986/* Enumeration - ns=0;i=29 */
52987
52988static UA_StatusCode function_namespace0_generated_32_begin(UA_Server *server, UA_UInt16* ns) {
52989UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52990UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52991attr.isAbstract = true;
52992attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Enumeration");
52993retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52994requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
52995parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52996referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52997browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Enumeration"),
52998 typeDefinition: UA_NODEID_NULL,
52999attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53000return retVal;
53001}
53002
53003static UA_StatusCode function_namespace0_generated_32_finish(UA_Server *server, UA_UInt16* ns) {
53004return UA_Server_addNode_finish(server,
53005nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU)
53006);
53007}
53008
53009/* ServerState - ns=0;i=852 */
53010
53011static UA_StatusCode function_namespace0_generated_33_begin(UA_Server *server, UA_UInt16* ns) {
53012UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53013UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53014attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerState");
53015retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53016requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU),
53017parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53018referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53019browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerState"),
53020 typeDefinition: UA_NODEID_NULL,
53021attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53022return retVal;
53023}
53024
53025static UA_StatusCode function_namespace0_generated_33_finish(UA_Server *server, UA_UInt16* ns) {
53026return UA_Server_addNode_finish(server,
53027nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU)
53028);
53029}
53030
53031/* RedundancySupport - ns=0;i=851 */
53032
53033static UA_StatusCode function_namespace0_generated_34_begin(UA_Server *server, UA_UInt16* ns) {
53034UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53035UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53036attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport");
53037retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53038requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU),
53039parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53040referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53041browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"),
53042 typeDefinition: UA_NODEID_NULL,
53043attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53044return retVal;
53045}
53046
53047static UA_StatusCode function_namespace0_generated_34_finish(UA_Server *server, UA_UInt16* ns) {
53048return UA_Server_addNode_finish(server,
53049nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU)
53050);
53051}
53052
53053/* EnumStrings - ns=0;i=7611 */
53054
53055static UA_StatusCode function_namespace0_generated_35_begin(UA_Server *server, UA_UInt16* ns) {
53056UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53057UA_VariableAttributes attr = UA_VariableAttributes_default;
53058attr.minimumSamplingInterval = 0.000000;
53059attr.userAccessLevel = 1;
53060attr.accessLevel = 1;
53061attr.valueRank = 1;
53062attr.arrayDimensionsSize = 1;
53063UA_UInt32 arrayDimensions[1];
53064arrayDimensions[0] = 0;
53065attr.arrayDimensions = &arrayDimensions[0];
53066attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53067UA_LocalizedText variablenode_ns_0_i_7611_variant_DataContents[6];
53068variablenode_ns_0_i_7611_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: "None");
53069variablenode_ns_0_i_7611_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: "Cold");
53070variablenode_ns_0_i_7611_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: "Warm");
53071variablenode_ns_0_i_7611_variant_DataContents[3] = UA_LOCALIZEDTEXT(locale: "", text: "Hot");
53072variablenode_ns_0_i_7611_variant_DataContents[4] = UA_LOCALIZEDTEXT(locale: "", text: "Transparent");
53073variablenode_ns_0_i_7611_variant_DataContents[5] = UA_LOCALIZEDTEXT(locale: "", text: "HotAndMirrored");
53074UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_7611_variant_DataContents, arraySize: (UA_Int32) 6, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
53075attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings");
53076retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53077requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7611LU),
53078parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU),
53079referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53080browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"),
53081typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53082attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53083return retVal;
53084}
53085
53086static UA_StatusCode function_namespace0_generated_35_finish(UA_Server *server, UA_UInt16* ns) {
53087return UA_Server_addNode_finish(server,
53088nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7611LU)
53089);
53090}
53091
53092/* AxisScaleEnumeration - ns=0;i=12077 */
53093
53094static UA_StatusCode function_namespace0_generated_36_begin(UA_Server *server, UA_UInt16* ns) {
53095UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53096UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53097attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AxisScaleEnumeration");
53098retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53099requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU),
53100parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53101referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53102browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AxisScaleEnumeration"),
53103 typeDefinition: UA_NODEID_NULL,
53104attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53105return retVal;
53106}
53107
53108static UA_StatusCode function_namespace0_generated_36_finish(UA_Server *server, UA_UInt16* ns) {
53109return UA_Server_addNode_finish(server,
53110nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU)
53111);
53112}
53113
53114/* EnumStrings - ns=0;i=12078 */
53115
53116static UA_StatusCode function_namespace0_generated_37_begin(UA_Server *server, UA_UInt16* ns) {
53117UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53118UA_VariableAttributes attr = UA_VariableAttributes_default;
53119attr.minimumSamplingInterval = 0.000000;
53120attr.userAccessLevel = 1;
53121attr.accessLevel = 1;
53122attr.valueRank = 1;
53123attr.arrayDimensionsSize = 1;
53124UA_UInt32 arrayDimensions[1];
53125arrayDimensions[0] = 0;
53126attr.arrayDimensions = &arrayDimensions[0];
53127attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53128UA_LocalizedText variablenode_ns_0_i_12078_variant_DataContents[3];
53129variablenode_ns_0_i_12078_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: "Linear");
53130variablenode_ns_0_i_12078_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: "Log");
53131variablenode_ns_0_i_12078_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: "Ln");
53132UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_12078_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
53133attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings");
53134retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53135requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12078LU),
53136parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU),
53137referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53138browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"),
53139typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53140attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53141return retVal;
53142}
53143
53144static UA_StatusCode function_namespace0_generated_37_finish(UA_Server *server, UA_UInt16* ns) {
53145return UA_Server_addNode_finish(server,
53146nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12078LU)
53147);
53148}
53149
53150/* NamingRuleType - ns=0;i=120 */
53151
53152static UA_StatusCode function_namespace0_generated_38_begin(UA_Server *server, UA_UInt16* ns) {
53153UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53154UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53155attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRuleType");
53156retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53157requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU),
53158parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53159referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53160browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRuleType"),
53161 typeDefinition: UA_NODEID_NULL,
53162attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53163return retVal;
53164}
53165
53166static UA_StatusCode function_namespace0_generated_38_finish(UA_Server *server, UA_UInt16* ns) {
53167return UA_Server_addNode_finish(server,
53168nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU)
53169);
53170}
53171
53172/* EnumValues - ns=0;i=12169 */
53173
53174static UA_StatusCode function_namespace0_generated_39_begin(UA_Server *server, UA_UInt16* ns) {
53175UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53176UA_VariableAttributes attr = UA_VariableAttributes_default;
53177attr.minimumSamplingInterval = 0.000000;
53178attr.userAccessLevel = 1;
53179attr.accessLevel = 1;
53180attr.valueRank = 1;
53181attr.arrayDimensionsSize = 1;
53182UA_UInt32 arrayDimensions[1];
53183arrayDimensions[0] = 0;
53184attr.arrayDimensions = &arrayDimensions[0];
53185attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU);
53186UA_EnumValueType variablenode_ns_0_i_12169_variant_DataContents[3];
53187
53188UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
53189variablenode_ns_0_i_12169_variant_DataContents[0].value = (UA_Int64) 1;
53190variablenode_ns_0_i_12169_variant_DataContents[0].displayName = UA_LOCALIZEDTEXT(locale: "", text: "Mandatory");
53191variablenode_ns_0_i_12169_variant_DataContents[0].description = UA_LOCALIZEDTEXT(locale: "", text: "The BrowseName must appear in all instances of the type.");
53192
53193UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
53194variablenode_ns_0_i_12169_variant_DataContents[1].value = (UA_Int64) 2;
53195variablenode_ns_0_i_12169_variant_DataContents[1].displayName = UA_LOCALIZEDTEXT(locale: "", text: "Optional");
53196variablenode_ns_0_i_12169_variant_DataContents[1].description = UA_LOCALIZEDTEXT(locale: "", text: "The BrowseName may appear in an instance of the type.");
53197
53198UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[2], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
53199variablenode_ns_0_i_12169_variant_DataContents[2].value = (UA_Int64) 3;
53200variablenode_ns_0_i_12169_variant_DataContents[2].displayName = UA_LOCALIZEDTEXT(locale: "", text: "Constraint");
53201variablenode_ns_0_i_12169_variant_DataContents[2].description = UA_LOCALIZEDTEXT(locale: "", text: "The modelling rule defines a constraint and the BrowseName is not used in an instance of the type.");
53202UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_12169_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
53203attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValues");
53204retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53205requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12169LU),
53206parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU),
53207referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53208browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValues"),
53209typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53210attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53211
53212
53213
53214return retVal;
53215}
53216
53217static UA_StatusCode function_namespace0_generated_39_finish(UA_Server *server, UA_UInt16* ns) {
53218return UA_Server_addNode_finish(server,
53219nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12169LU)
53220);
53221}
53222
53223/* Number - ns=0;i=26 */
53224
53225static UA_StatusCode function_namespace0_generated_40_begin(UA_Server *server, UA_UInt16* ns) {
53226UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53227UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53228attr.isAbstract = true;
53229attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Number");
53230retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53231requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53232parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
53233referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53234browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Number"),
53235 typeDefinition: UA_NODEID_NULL,
53236attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53237return retVal;
53238}
53239
53240static UA_StatusCode function_namespace0_generated_40_finish(UA_Server *server, UA_UInt16* ns) {
53241return UA_Server_addNode_finish(server,
53242nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU)
53243);
53244}
53245
53246/* Decimal - ns=0;i=50 */
53247
53248static UA_StatusCode function_namespace0_generated_41_begin(UA_Server *server, UA_UInt16* ns) {
53249UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53250UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53251attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Decimal");
53252retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53253requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 50LU),
53254parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53255referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53256browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Decimal"),
53257 typeDefinition: UA_NODEID_NULL,
53258attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53259return retVal;
53260}
53261
53262static UA_StatusCode function_namespace0_generated_41_finish(UA_Server *server, UA_UInt16* ns) {
53263return UA_Server_addNode_finish(server,
53264nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 50LU)
53265);
53266}
53267
53268/* UInteger - ns=0;i=28 */
53269
53270static UA_StatusCode function_namespace0_generated_42_begin(UA_Server *server, UA_UInt16* ns) {
53271UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53272UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53273attr.isAbstract = true;
53274attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInteger");
53275retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53276requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53277parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53278referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53279browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInteger"),
53280 typeDefinition: UA_NODEID_NULL,
53281attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53282return retVal;
53283}
53284
53285static UA_StatusCode function_namespace0_generated_42_finish(UA_Server *server, UA_UInt16* ns) {
53286return UA_Server_addNode_finish(server,
53287nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU)
53288);
53289}
53290
53291/* UInt64 - ns=0;i=9 */
53292
53293static UA_StatusCode function_namespace0_generated_43_begin(UA_Server *server, UA_UInt16* ns) {
53294UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53295UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53296attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt64");
53297retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53298requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9LU),
53299parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53300referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53301browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt64"),
53302 typeDefinition: UA_NODEID_NULL,
53303attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53304return retVal;
53305}
53306
53307static UA_StatusCode function_namespace0_generated_43_finish(UA_Server *server, UA_UInt16* ns) {
53308return UA_Server_addNode_finish(server,
53309nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9LU)
53310);
53311}
53312
53313/* UInt32 - ns=0;i=7 */
53314
53315static UA_StatusCode function_namespace0_generated_44_begin(UA_Server *server, UA_UInt16* ns) {
53316UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53317UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53318attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt32");
53319retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53320requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU),
53321parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53322referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53323browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt32"),
53324 typeDefinition: UA_NODEID_NULL,
53325attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53326return retVal;
53327}
53328
53329static UA_StatusCode function_namespace0_generated_44_finish(UA_Server *server, UA_UInt16* ns) {
53330return UA_Server_addNode_finish(server,
53331nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU)
53332);
53333}
53334
53335/* UInt16 - ns=0;i=5 */
53336
53337static UA_StatusCode function_namespace0_generated_45_begin(UA_Server *server, UA_UInt16* ns) {
53338UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53339UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53340attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt16");
53341retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53342requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU),
53343parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53344referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53345browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt16"),
53346 typeDefinition: UA_NODEID_NULL,
53347attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53348return retVal;
53349}
53350
53351static UA_StatusCode function_namespace0_generated_45_finish(UA_Server *server, UA_UInt16* ns) {
53352return UA_Server_addNode_finish(server,
53353nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU)
53354);
53355}
53356
53357/* Byte - ns=0;i=3 */
53358
53359static UA_StatusCode function_namespace0_generated_46_begin(UA_Server *server, UA_UInt16* ns) {
53360UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53361UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53362attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Byte");
53363retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53364requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU),
53365parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53366referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53367browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Byte"),
53368 typeDefinition: UA_NODEID_NULL,
53369attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53370return retVal;
53371}
53372
53373static UA_StatusCode function_namespace0_generated_46_finish(UA_Server *server, UA_UInt16* ns) {
53374return UA_Server_addNode_finish(server,
53375nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU)
53376);
53377}
53378
53379/* Integer - ns=0;i=27 */
53380
53381static UA_StatusCode function_namespace0_generated_47_begin(UA_Server *server, UA_UInt16* ns) {
53382UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53383UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53384attr.isAbstract = true;
53385attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Integer");
53386retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53387requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53388parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53389referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53390browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Integer"),
53391 typeDefinition: UA_NODEID_NULL,
53392attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53393return retVal;
53394}
53395
53396static UA_StatusCode function_namespace0_generated_47_finish(UA_Server *server, UA_UInt16* ns) {
53397return UA_Server_addNode_finish(server,
53398nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU)
53399);
53400}
53401
53402/* Int64 - ns=0;i=8 */
53403
53404static UA_StatusCode function_namespace0_generated_48_begin(UA_Server *server, UA_UInt16* ns) {
53405UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53406UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53407attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int64");
53408retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53409requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8LU),
53410parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53411referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53412browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int64"),
53413 typeDefinition: UA_NODEID_NULL,
53414attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53415return retVal;
53416}
53417
53418static UA_StatusCode function_namespace0_generated_48_finish(UA_Server *server, UA_UInt16* ns) {
53419return UA_Server_addNode_finish(server,
53420nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8LU)
53421);
53422}
53423
53424/* Int32 - ns=0;i=6 */
53425
53426static UA_StatusCode function_namespace0_generated_49_begin(UA_Server *server, UA_UInt16* ns) {
53427UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53428UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53429attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int32");
53430retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53431requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 6LU),
53432parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53433referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53434browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int32"),
53435 typeDefinition: UA_NODEID_NULL,
53436attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53437return retVal;
53438}
53439
53440static UA_StatusCode function_namespace0_generated_49_finish(UA_Server *server, UA_UInt16* ns) {
53441return UA_Server_addNode_finish(server,
53442nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 6LU)
53443);
53444}
53445
53446/* Int16 - ns=0;i=4 */
53447
53448static UA_StatusCode function_namespace0_generated_50_begin(UA_Server *server, UA_UInt16* ns) {
53449UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53450UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53451attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int16");
53452retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53453requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 4LU),
53454parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53455referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53456browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int16"),
53457 typeDefinition: UA_NODEID_NULL,
53458attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53459return retVal;
53460}
53461
53462static UA_StatusCode function_namespace0_generated_50_finish(UA_Server *server, UA_UInt16* ns) {
53463return UA_Server_addNode_finish(server,
53464nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 4LU)
53465);
53466}
53467
53468/* SByte - ns=0;i=2 */
53469
53470static UA_StatusCode function_namespace0_generated_51_begin(UA_Server *server, UA_UInt16* ns) {
53471UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53472UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53473attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SByte");
53474retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53475requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2LU),
53476parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53477referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53478browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SByte"),
53479 typeDefinition: UA_NODEID_NULL,
53480attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53481return retVal;
53482}
53483
53484static UA_StatusCode function_namespace0_generated_51_finish(UA_Server *server, UA_UInt16* ns) {
53485return UA_Server_addNode_finish(server,
53486nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2LU)
53487);
53488}
53489
53490/* Double - ns=0;i=11 */
53491
53492static UA_StatusCode function_namespace0_generated_52_begin(UA_Server *server, UA_UInt16* ns) {
53493UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53494UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53495attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Double");
53496retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53497requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU),
53498parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53499referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53500browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Double"),
53501 typeDefinition: UA_NODEID_NULL,
53502attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53503return retVal;
53504}
53505
53506static UA_StatusCode function_namespace0_generated_52_finish(UA_Server *server, UA_UInt16* ns) {
53507return UA_Server_addNode_finish(server,
53508nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU)
53509);
53510}
53511
53512/* Duration - ns=0;i=290 */
53513
53514static UA_StatusCode function_namespace0_generated_53_begin(UA_Server *server, UA_UInt16* ns) {
53515UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53516UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53517attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Duration");
53518retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53519requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU),
53520parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU),
53521referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53522browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Duration"),
53523 typeDefinition: UA_NODEID_NULL,
53524attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53525return retVal;
53526}
53527
53528static UA_StatusCode function_namespace0_generated_53_finish(UA_Server *server, UA_UInt16* ns) {
53529return UA_Server_addNode_finish(server,
53530nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU)
53531);
53532}
53533
53534/* Float - ns=0;i=10 */
53535
53536static UA_StatusCode function_namespace0_generated_54_begin(UA_Server *server, UA_UInt16* ns) {
53537UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53538UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53539attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Float");
53540retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53541requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 10LU),
53542parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53543referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53544browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Float"),
53545 typeDefinition: UA_NODEID_NULL,
53546attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53547return retVal;
53548}
53549
53550static UA_StatusCode function_namespace0_generated_54_finish(UA_Server *server, UA_UInt16* ns) {
53551return UA_Server_addNode_finish(server,
53552nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 10LU)
53553);
53554}
53555
53556/* DataItemType - ns=0;i=2365 */
53557
53558static UA_StatusCode function_namespace0_generated_55_begin(UA_Server *server, UA_UInt16* ns) {
53559UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53560UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53561attr.valueRank = -2;
53562/* DataType inherited */
53563attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU);
53564attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataItemType");
53565#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
53566attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A variable that contains live automation data.");
53567#endif
53568retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53569requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
53570parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
53571referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53572browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataItemType"),
53573typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53574attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53575return retVal;
53576}
53577
53578static UA_StatusCode function_namespace0_generated_55_finish(UA_Server *server, UA_UInt16* ns) {
53579return UA_Server_addNode_finish(server,
53580nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU)
53581);
53582}
53583
53584/* DiscreteItemType - ns=0;i=2372 */
53585
53586static UA_StatusCode function_namespace0_generated_56_begin(UA_Server *server, UA_UInt16* ns) {
53587UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53588UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53589attr.isAbstract = true;
53590attr.valueRank = -2;
53591/* DataType inherited */
53592attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU);
53593attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DiscreteItemType");
53594retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53595requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU),
53596parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
53597referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53598browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DiscreteItemType"),
53599typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53600attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53601return retVal;
53602}
53603
53604static UA_StatusCode function_namespace0_generated_56_finish(UA_Server *server, UA_UInt16* ns) {
53605return UA_Server_addNode_finish(server,
53606nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU)
53607);
53608}
53609
53610/* MultiStateDiscreteType - ns=0;i=2376 */
53611
53612static UA_StatusCode function_namespace0_generated_57_begin(UA_Server *server, UA_UInt16* ns) {
53613UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53614UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53615attr.valueRank = -2;
53616attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU);
53617attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MultiStateDiscreteType");
53618retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53619requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU),
53620parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU),
53621referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53622browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MultiStateDiscreteType"),
53623typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53624attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53625return retVal;
53626}
53627
53628static UA_StatusCode function_namespace0_generated_57_finish(UA_Server *server, UA_UInt16* ns) {
53629return UA_Server_addNode_finish(server,
53630nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU)
53631);
53632}
53633
53634/* EnumStrings - ns=0;i=2377 */
53635
53636static UA_StatusCode function_namespace0_generated_58_begin(UA_Server *server, UA_UInt16* ns) {
53637UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53638UA_VariableAttributes attr = UA_VariableAttributes_default;
53639attr.minimumSamplingInterval = 0.000000;
53640attr.userAccessLevel = 1;
53641attr.accessLevel = 1;
53642attr.valueRank = 1;
53643attr.arrayDimensionsSize = 1;
53644UA_UInt32 arrayDimensions[1];
53645arrayDimensions[0] = 0;
53646attr.arrayDimensions = &arrayDimensions[0];
53647attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53648attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings");
53649retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53650requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2377LU),
53651parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU),
53652referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53653browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"),
53654typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53655attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53656return retVal;
53657}
53658
53659static UA_StatusCode function_namespace0_generated_58_finish(UA_Server *server, UA_UInt16* ns) {
53660return UA_Server_addNode_finish(server,
53661nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2377LU)
53662);
53663}
53664
53665/* TwoStateDiscreteType - ns=0;i=2373 */
53666
53667static UA_StatusCode function_namespace0_generated_59_begin(UA_Server *server, UA_UInt16* ns) {
53668UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53669UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53670attr.valueRank = -2;
53671attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
53672attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TwoStateDiscreteType");
53673retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53674requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU),
53675parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU),
53676referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53677browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TwoStateDiscreteType"),
53678typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53679attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53680return retVal;
53681}
53682
53683static UA_StatusCode function_namespace0_generated_59_finish(UA_Server *server, UA_UInt16* ns) {
53684return UA_Server_addNode_finish(server,
53685nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU)
53686);
53687}
53688
53689/* TrueState - ns=0;i=2375 */
53690
53691static UA_StatusCode function_namespace0_generated_60_begin(UA_Server *server, UA_UInt16* ns) {
53692UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53693UA_VariableAttributes attr = UA_VariableAttributes_default;
53694attr.minimumSamplingInterval = 0.000000;
53695attr.userAccessLevel = 1;
53696attr.accessLevel = 1;
53697/* Value rank inherited */
53698attr.valueRank = -2;
53699attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53700attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TrueState");
53701retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53702requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2375LU),
53703parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU),
53704referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53705browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TrueState"),
53706typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53707attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53708return retVal;
53709}
53710
53711static UA_StatusCode function_namespace0_generated_60_finish(UA_Server *server, UA_UInt16* ns) {
53712return UA_Server_addNode_finish(server,
53713nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2375LU)
53714);
53715}
53716
53717/* FalseState - ns=0;i=2374 */
53718
53719static UA_StatusCode function_namespace0_generated_61_begin(UA_Server *server, UA_UInt16* ns) {
53720UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53721UA_VariableAttributes attr = UA_VariableAttributes_default;
53722attr.minimumSamplingInterval = 0.000000;
53723attr.userAccessLevel = 1;
53724attr.accessLevel = 1;
53725/* Value rank inherited */
53726attr.valueRank = -2;
53727attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53728attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FalseState");
53729retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53730requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2374LU),
53731parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU),
53732referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53733browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FalseState"),
53734typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53735attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53736return retVal;
53737}
53738
53739static UA_StatusCode function_namespace0_generated_61_finish(UA_Server *server, UA_UInt16* ns) {
53740return UA_Server_addNode_finish(server,
53741nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2374LU)
53742);
53743}
53744
53745/* MultiStateValueDiscreteType - ns=0;i=11238 */
53746
53747static UA_StatusCode function_namespace0_generated_62_begin(UA_Server *server, UA_UInt16* ns) {
53748UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53749UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53750attr.valueRank = -2;
53751attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU);
53752attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MultiStateValueDiscreteType");
53753retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53754requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU),
53755parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU),
53756referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53757browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MultiStateValueDiscreteType"),
53758typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53759attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53760return retVal;
53761}
53762
53763static UA_StatusCode function_namespace0_generated_62_finish(UA_Server *server, UA_UInt16* ns) {
53764return UA_Server_addNode_finish(server,
53765nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU)
53766);
53767}
53768
53769/* ValueAsText - ns=0;i=11461 */
53770
53771static UA_StatusCode function_namespace0_generated_63_begin(UA_Server *server, UA_UInt16* ns) {
53772UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53773UA_VariableAttributes attr = UA_VariableAttributes_default;
53774attr.minimumSamplingInterval = 0.000000;
53775attr.userAccessLevel = 1;
53776attr.accessLevel = 1;
53777/* Value rank inherited */
53778attr.valueRank = -2;
53779attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53780attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ValueAsText");
53781retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53782requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11461LU),
53783parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU),
53784referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53785browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ValueAsText"),
53786typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53787attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53788return retVal;
53789}
53790
53791static UA_StatusCode function_namespace0_generated_63_finish(UA_Server *server, UA_UInt16* ns) {
53792return UA_Server_addNode_finish(server,
53793nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11461LU)
53794);
53795}
53796
53797/* EnumValues - ns=0;i=11241 */
53798
53799static UA_StatusCode function_namespace0_generated_64_begin(UA_Server *server, UA_UInt16* ns) {
53800UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53801UA_VariableAttributes attr = UA_VariableAttributes_default;
53802attr.minimumSamplingInterval = 0.000000;
53803attr.userAccessLevel = 1;
53804attr.accessLevel = 1;
53805attr.valueRank = 1;
53806attr.arrayDimensionsSize = 1;
53807UA_UInt32 arrayDimensions[1];
53808arrayDimensions[0] = 0;
53809attr.arrayDimensions = &arrayDimensions[0];
53810attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU);
53811attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValues");
53812retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53813requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11241LU),
53814parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU),
53815referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53816browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValues"),
53817typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53818attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53819return retVal;
53820}
53821
53822static UA_StatusCode function_namespace0_generated_64_finish(UA_Server *server, UA_UInt16* ns) {
53823return UA_Server_addNode_finish(server,
53824nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11241LU)
53825);
53826}
53827
53828/* AnalogItemType - ns=0;i=2368 */
53829
53830static UA_StatusCode function_namespace0_generated_65_begin(UA_Server *server, UA_UInt16* ns) {
53831UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53832UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53833attr.valueRank = -2;
53834attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU);
53835attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AnalogItemType");
53836retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53837requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU),
53838parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
53839referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53840browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AnalogItemType"),
53841typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53842attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53843return retVal;
53844}
53845
53846static UA_StatusCode function_namespace0_generated_65_finish(UA_Server *server, UA_UInt16* ns) {
53847return UA_Server_addNode_finish(server,
53848nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU)
53849);
53850}
53851
53852/* EngineeringUnits - ns=0;i=2371 */
53853
53854static UA_StatusCode function_namespace0_generated_66_begin(UA_Server *server, UA_UInt16* ns) {
53855UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53856UA_VariableAttributes attr = UA_VariableAttributes_default;
53857attr.minimumSamplingInterval = 0.000000;
53858attr.userAccessLevel = 1;
53859attr.accessLevel = 1;
53860/* Value rank inherited */
53861attr.valueRank = -2;
53862attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU);
53863attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EngineeringUnits");
53864retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53865requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2371LU),
53866parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU),
53867referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53868browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EngineeringUnits"),
53869typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53870attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53871return retVal;
53872}
53873
53874static UA_StatusCode function_namespace0_generated_66_finish(UA_Server *server, UA_UInt16* ns) {
53875return UA_Server_addNode_finish(server,
53876nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2371LU)
53877);
53878}
53879
53880/* InstrumentRange - ns=0;i=2370 */
53881
53882static UA_StatusCode function_namespace0_generated_67_begin(UA_Server *server, UA_UInt16* ns) {
53883UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53884UA_VariableAttributes attr = UA_VariableAttributes_default;
53885attr.minimumSamplingInterval = 0.000000;
53886attr.userAccessLevel = 1;
53887attr.accessLevel = 1;
53888/* Value rank inherited */
53889attr.valueRank = -2;
53890attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU);
53891attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InstrumentRange");
53892retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53893requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2370LU),
53894parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU),
53895referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53896browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InstrumentRange"),
53897typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53898attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53899return retVal;
53900}
53901
53902static UA_StatusCode function_namespace0_generated_67_finish(UA_Server *server, UA_UInt16* ns) {
53903return UA_Server_addNode_finish(server,
53904nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2370LU)
53905);
53906}
53907
53908/* EURange - ns=0;i=2369 */
53909
53910static UA_StatusCode function_namespace0_generated_68_begin(UA_Server *server, UA_UInt16* ns) {
53911UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53912UA_VariableAttributes attr = UA_VariableAttributes_default;
53913attr.minimumSamplingInterval = 0.000000;
53914attr.userAccessLevel = 3;
53915attr.accessLevel = 3;
53916/* Value rank inherited */
53917attr.valueRank = -2;
53918attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU);
53919attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EURange");
53920retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53921requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2369LU),
53922parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU),
53923referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53924browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EURange"),
53925typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53926attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53927return retVal;
53928}
53929
53930static UA_StatusCode function_namespace0_generated_68_finish(UA_Server *server, UA_UInt16* ns) {
53931return UA_Server_addNode_finish(server,
53932nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2369LU)
53933);
53934}
53935
53936/* ValuePrecision - ns=0;i=2367 */
53937
53938static UA_StatusCode function_namespace0_generated_69_begin(UA_Server *server, UA_UInt16* ns) {
53939UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53940UA_VariableAttributes attr = UA_VariableAttributes_default;
53941attr.minimumSamplingInterval = 0.000000;
53942attr.userAccessLevel = 1;
53943attr.accessLevel = 1;
53944/* Value rank inherited */
53945attr.valueRank = -2;
53946attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU);
53947attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ValuePrecision");
53948#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
53949attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The maximum precision that the server can maintain for the item based on restrictions in the target environment.");
53950#endif
53951retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53952requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2367LU),
53953parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
53954referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53955browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ValuePrecision"),
53956typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53957attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53958return retVal;
53959}
53960
53961static UA_StatusCode function_namespace0_generated_69_finish(UA_Server *server, UA_UInt16* ns) {
53962return UA_Server_addNode_finish(server,
53963nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2367LU)
53964);
53965}
53966
53967/* Definition - ns=0;i=2366 */
53968
53969static UA_StatusCode function_namespace0_generated_70_begin(UA_Server *server, UA_UInt16* ns) {
53970UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53971UA_VariableAttributes attr = UA_VariableAttributes_default;
53972attr.minimumSamplingInterval = 0.000000;
53973attr.userAccessLevel = 1;
53974attr.accessLevel = 1;
53975/* Value rank inherited */
53976attr.valueRank = -2;
53977attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
53978attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Definition");
53979#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
53980attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A vendor-specific, human readable string that specifies how the value of this DataItem is calculated.");
53981#endif
53982retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53983requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2366LU),
53984parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
53985referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53986browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Definition"),
53987typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53988attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53989return retVal;
53990}
53991
53992static UA_StatusCode function_namespace0_generated_70_finish(UA_Server *server, UA_UInt16* ns) {
53993return UA_Server_addNode_finish(server,
53994nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2366LU)
53995);
53996}
53997
53998/* HistoryServerCapabilitiesType - ns=0;i=2330 */
53999
54000static UA_StatusCode function_namespace0_generated_71_begin(UA_Server *server, UA_UInt16* ns) {
54001UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54002UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54003attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryServerCapabilitiesType");
54004retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54005requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU),
54006parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54007referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54008browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryServerCapabilitiesType"),
54009 typeDefinition: UA_NODEID_NULL,
54010attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54011return retVal;
54012}
54013
54014static UA_StatusCode function_namespace0_generated_71_finish(UA_Server *server, UA_UInt16* ns) {
54015return UA_Server_addNode_finish(server,
54016nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU)
54017);
54018}
54019
54020/* EventQueueOverflowEventType - ns=0;i=3035 */
54021
54022static UA_StatusCode function_namespace0_generated_72_begin(UA_Server *server, UA_UInt16* ns) {
54023UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54024UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54025attr.isAbstract = true;
54026attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventQueueOverflowEventType");
54027retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54028requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3035LU),
54029parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54030referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54031browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventQueueOverflowEventType"),
54032 typeDefinition: UA_NODEID_NULL,
54033attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54034return retVal;
54035}
54036
54037static UA_StatusCode function_namespace0_generated_72_finish(UA_Server *server, UA_UInt16* ns) {
54038return UA_Server_addNode_finish(server,
54039nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3035LU)
54040);
54041}
54042
54043/* Severity - ns=0;i=2051 */
54044
54045static UA_StatusCode function_namespace0_generated_73_begin(UA_Server *server, UA_UInt16* ns) {
54046UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54047UA_VariableAttributes attr = UA_VariableAttributes_default;
54048attr.minimumSamplingInterval = 0.000000;
54049attr.userAccessLevel = 1;
54050attr.accessLevel = 1;
54051/* Value rank inherited */
54052attr.valueRank = -2;
54053attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU);
54054attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Severity");
54055#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54056attr.description = UA_LOCALIZEDTEXT(locale: "", text: "Indicates how urgent an event is.");
54057#endif
54058retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54059requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2051LU),
54060parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54061referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54062browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Severity"),
54063typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54064attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54065return retVal;
54066}
54067
54068static UA_StatusCode function_namespace0_generated_73_finish(UA_Server *server, UA_UInt16* ns) {
54069return UA_Server_addNode_finish(server,
54070nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2051LU)
54071);
54072}
54073
54074/* Message - ns=0;i=2050 */
54075
54076static UA_StatusCode function_namespace0_generated_74_begin(UA_Server *server, UA_UInt16* ns) {
54077UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54078UA_VariableAttributes attr = UA_VariableAttributes_default;
54079attr.minimumSamplingInterval = 0.000000;
54080attr.userAccessLevel = 1;
54081attr.accessLevel = 1;
54082/* Value rank inherited */
54083attr.valueRank = -2;
54084attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
54085attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Message");
54086#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54087attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A localized description of the event.");
54088#endif
54089retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54090requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2050LU),
54091parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54092referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54093browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Message"),
54094typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54095attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54096return retVal;
54097}
54098
54099static UA_StatusCode function_namespace0_generated_74_finish(UA_Server *server, UA_UInt16* ns) {
54100return UA_Server_addNode_finish(server,
54101nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2050LU)
54102);
54103}
54104
54105/* LocalTime - ns=0;i=3190 */
54106
54107static UA_StatusCode function_namespace0_generated_75_begin(UA_Server *server, UA_UInt16* ns) {
54108UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54109UA_VariableAttributes attr = UA_VariableAttributes_default;
54110attr.minimumSamplingInterval = 0.000000;
54111attr.userAccessLevel = 1;
54112attr.accessLevel = 1;
54113/* Value rank inherited */
54114attr.valueRank = -2;
54115attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU);
54116attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocalTime");
54117#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54118attr.description = UA_LOCALIZEDTEXT(locale: "", text: "Information about the local time where the event originated.");
54119#endif
54120retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54121requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3190LU),
54122parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54123referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54124browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocalTime"),
54125typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54126attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54127return retVal;
54128}
54129
54130static UA_StatusCode function_namespace0_generated_75_finish(UA_Server *server, UA_UInt16* ns) {
54131return UA_Server_addNode_finish(server,
54132nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3190LU)
54133);
54134}
54135
54136/* ReceiveTime - ns=0;i=2047 */
54137
54138static UA_StatusCode function_namespace0_generated_76_begin(UA_Server *server, UA_UInt16* ns) {
54139UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54140UA_VariableAttributes attr = UA_VariableAttributes_default;
54141attr.minimumSamplingInterval = 0.000000;
54142attr.userAccessLevel = 1;
54143attr.accessLevel = 1;
54144/* Value rank inherited */
54145attr.valueRank = -2;
54146attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
54147attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReceiveTime");
54148#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54149attr.description = UA_LOCALIZEDTEXT(locale: "", text: "When the server received the event from the underlying system.");
54150#endif
54151retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54152requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2047LU),
54153parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54154referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54155browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReceiveTime"),
54156typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54157attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54158return retVal;
54159}
54160
54161static UA_StatusCode function_namespace0_generated_76_finish(UA_Server *server, UA_UInt16* ns) {
54162return UA_Server_addNode_finish(server,
54163nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2047LU)
54164);
54165}
54166
54167/* Time - ns=0;i=2046 */
54168
54169static UA_StatusCode function_namespace0_generated_77_begin(UA_Server *server, UA_UInt16* ns) {
54170UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54171UA_VariableAttributes attr = UA_VariableAttributes_default;
54172attr.minimumSamplingInterval = 0.000000;
54173attr.userAccessLevel = 1;
54174attr.accessLevel = 1;
54175/* Value rank inherited */
54176attr.valueRank = -2;
54177attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
54178attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Time");
54179#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54180attr.description = UA_LOCALIZEDTEXT(locale: "", text: "When the event occurred.");
54181#endif
54182retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54183requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2046LU),
54184parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54185referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54186browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Time"),
54187typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54188attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54189return retVal;
54190}
54191
54192static UA_StatusCode function_namespace0_generated_77_finish(UA_Server *server, UA_UInt16* ns) {
54193return UA_Server_addNode_finish(server,
54194nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2046LU)
54195);
54196}
54197
54198/* SourceName - ns=0;i=2045 */
54199
54200static UA_StatusCode function_namespace0_generated_78_begin(UA_Server *server, UA_UInt16* ns) {
54201UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54202UA_VariableAttributes attr = UA_VariableAttributes_default;
54203attr.minimumSamplingInterval = 0.000000;
54204attr.userAccessLevel = 1;
54205attr.accessLevel = 1;
54206/* Value rank inherited */
54207attr.valueRank = -2;
54208attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
54209attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceName");
54210#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54211attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A description of the source of the event.");
54212#endif
54213retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54214requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2045LU),
54215parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54216referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54217browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceName"),
54218typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54219attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54220return retVal;
54221}
54222
54223static UA_StatusCode function_namespace0_generated_78_finish(UA_Server *server, UA_UInt16* ns) {
54224return UA_Server_addNode_finish(server,
54225nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2045LU)
54226);
54227}
54228
54229/* SourceNode - ns=0;i=2044 */
54230
54231static UA_StatusCode function_namespace0_generated_79_begin(UA_Server *server, UA_UInt16* ns) {
54232UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54233UA_VariableAttributes attr = UA_VariableAttributes_default;
54234attr.minimumSamplingInterval = 0.000000;
54235attr.userAccessLevel = 1;
54236attr.accessLevel = 1;
54237/* Value rank inherited */
54238attr.valueRank = -2;
54239attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU);
54240attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceNode");
54241#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54242attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The source of the event.");
54243#endif
54244retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54245requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2044LU),
54246parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54247referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54248browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceNode"),
54249typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54250attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54251return retVal;
54252}
54253
54254static UA_StatusCode function_namespace0_generated_79_finish(UA_Server *server, UA_UInt16* ns) {
54255return UA_Server_addNode_finish(server,
54256nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2044LU)
54257);
54258}
54259
54260/* EventType - ns=0;i=2043 */
54261
54262static UA_StatusCode function_namespace0_generated_80_begin(UA_Server *server, UA_UInt16* ns) {
54263UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54264UA_VariableAttributes attr = UA_VariableAttributes_default;
54265attr.minimumSamplingInterval = 0.000000;
54266attr.userAccessLevel = 1;
54267attr.accessLevel = 1;
54268/* Value rank inherited */
54269attr.valueRank = -2;
54270attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU);
54271attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventType");
54272#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54273attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The identifier for the event type.");
54274#endif
54275retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54276requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2043LU),
54277parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54278referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54279browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventType"),
54280typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54281attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54282return retVal;
54283}
54284
54285static UA_StatusCode function_namespace0_generated_80_finish(UA_Server *server, UA_UInt16* ns) {
54286return UA_Server_addNode_finish(server,
54287nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2043LU)
54288);
54289}
54290
54291/* EventId - ns=0;i=2042 */
54292
54293static UA_StatusCode function_namespace0_generated_81_begin(UA_Server *server, UA_UInt16* ns) {
54294UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54295UA_VariableAttributes attr = UA_VariableAttributes_default;
54296attr.minimumSamplingInterval = 0.000000;
54297attr.userAccessLevel = 1;
54298attr.accessLevel = 1;
54299/* Value rank inherited */
54300attr.valueRank = -2;
54301attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU);
54302attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventId");
54303#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54304attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A globally unique identifier for the event.");
54305#endif
54306retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54307requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2042LU),
54308parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54309referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54310browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventId"),
54311typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54312attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54313return retVal;
54314}
54315
54316static UA_StatusCode function_namespace0_generated_81_finish(UA_Server *server, UA_UInt16* ns) {
54317return UA_Server_addNode_finish(server,
54318nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2042LU)
54319);
54320}
54321
54322/* InterfaceTypes - ns=0;i=17708 */
54323
54324static UA_StatusCode function_namespace0_generated_82_begin(UA_Server *server, UA_UInt16* ns) {
54325UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54326UA_ObjectAttributes attr = UA_ObjectAttributes_default;
54327attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InterfaceTypes");
54328retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54329requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17708LU),
54330parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 86LU),
54331referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU),
54332browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InterfaceTypes"),
54333typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
54334attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
54335return retVal;
54336}
54337
54338static UA_StatusCode function_namespace0_generated_82_finish(UA_Server *server, UA_UInt16* ns) {
54339return UA_Server_addNode_finish(server,
54340nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17708LU)
54341);
54342}
54343
54344/* BaseInterfaceType - ns=0;i=17602 */
54345
54346static UA_StatusCode function_namespace0_generated_83_begin(UA_Server *server, UA_UInt16* ns) {
54347UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54348UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54349attr.isAbstract = true;
54350attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseInterfaceType");
54351retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54352requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17602LU),
54353parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54354referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54355browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BaseInterfaceType"),
54356 typeDefinition: UA_NODEID_NULL,
54357attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54358retVal |= 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);
54359return retVal;
54360}
54361
54362static UA_StatusCode function_namespace0_generated_83_finish(UA_Server *server, UA_UInt16* ns) {
54363return UA_Server_addNode_finish(server,
54364nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17602LU)
54365);
54366}
54367
54368/* BuildInfoType - ns=0;i=3051 */
54369
54370static UA_StatusCode function_namespace0_generated_84_begin(UA_Server *server, UA_UInt16* ns) {
54371UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54372UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
54373/* Value rank inherited */
54374attr.valueRank = -2;
54375attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU);
54376attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfoType");
54377retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
54378requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU),
54379parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
54380referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54381browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfoType"),
54382typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
54383attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
54384return retVal;
54385}
54386
54387static UA_StatusCode function_namespace0_generated_84_finish(UA_Server *server, UA_UInt16* ns) {
54388return UA_Server_addNode_finish(server,
54389nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU)
54390);
54391}
54392
54393/* ServerStatusType - ns=0;i=2138 */
54394
54395static UA_StatusCode function_namespace0_generated_85_begin(UA_Server *server, UA_UInt16* ns) {
54396UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54397UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
54398/* Value rank inherited */
54399attr.valueRank = -2;
54400attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU);
54401attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatusType");
54402retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
54403requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU),
54404parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
54405referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54406browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatusType"),
54407typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
54408attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
54409return retVal;
54410}
54411
54412static UA_StatusCode function_namespace0_generated_85_finish(UA_Server *server, UA_UInt16* ns) {
54413return UA_Server_addNode_finish(server,
54414nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU)
54415);
54416}
54417
54418/* OperationLimitsType - ns=0;i=11564 */
54419
54420static UA_StatusCode function_namespace0_generated_86_begin(UA_Server *server, UA_UInt16* ns) {
54421UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54422UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54423attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OperationLimitsType");
54424retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54425requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54426parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
54427referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54428browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimitsType"),
54429 typeDefinition: UA_NODEID_NULL,
54430attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54431return retVal;
54432}
54433
54434static UA_StatusCode function_namespace0_generated_86_finish(UA_Server *server, UA_UInt16* ns) {
54435return UA_Server_addNode_finish(server,
54436nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU)
54437);
54438}
54439
54440/* MaxMonitoredItemsPerCall - ns=0;i=11574 */
54441
54442static UA_StatusCode function_namespace0_generated_87_begin(UA_Server *server, UA_UInt16* ns) {
54443UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54444UA_VariableAttributes attr = UA_VariableAttributes_default;
54445attr.minimumSamplingInterval = 0.000000;
54446attr.userAccessLevel = 1;
54447attr.accessLevel = 1;
54448/* Value rank inherited */
54449attr.valueRank = -2;
54450attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54451attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxMonitoredItemsPerCall");
54452retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54453requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11574LU),
54454parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54455referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54456browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxMonitoredItemsPerCall"),
54457typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54458attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54459return retVal;
54460}
54461
54462static UA_StatusCode function_namespace0_generated_87_finish(UA_Server *server, UA_UInt16* ns) {
54463return UA_Server_addNode_finish(server,
54464nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11574LU)
54465);
54466}
54467
54468/* MaxNodesPerNodeManagement - ns=0;i=11573 */
54469
54470static UA_StatusCode function_namespace0_generated_88_begin(UA_Server *server, UA_UInt16* ns) {
54471UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54472UA_VariableAttributes attr = UA_VariableAttributes_default;
54473attr.minimumSamplingInterval = 0.000000;
54474attr.userAccessLevel = 1;
54475attr.accessLevel = 1;
54476/* Value rank inherited */
54477attr.valueRank = -2;
54478attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54479attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerNodeManagement");
54480retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54481requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11573LU),
54482parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54483referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54484browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerNodeManagement"),
54485typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54486attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54487return retVal;
54488}
54489
54490static UA_StatusCode function_namespace0_generated_88_finish(UA_Server *server, UA_UInt16* ns) {
54491return UA_Server_addNode_finish(server,
54492nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11573LU)
54493);
54494}
54495
54496/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11572 */
54497
54498static UA_StatusCode function_namespace0_generated_89_begin(UA_Server *server, UA_UInt16* ns) {
54499UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54500UA_VariableAttributes attr = UA_VariableAttributes_default;
54501attr.minimumSamplingInterval = 0.000000;
54502attr.userAccessLevel = 1;
54503attr.accessLevel = 1;
54504/* Value rank inherited */
54505attr.valueRank = -2;
54506attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54507attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerTranslateBrowsePathsToNodeIds");
54508retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54509requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11572LU),
54510parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54511referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54512browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerTranslateBrowsePathsToNodeIds"),
54513typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54514attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54515return retVal;
54516}
54517
54518static UA_StatusCode function_namespace0_generated_89_finish(UA_Server *server, UA_UInt16* ns) {
54519return UA_Server_addNode_finish(server,
54520nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11572LU)
54521);
54522}
54523
54524/* MaxNodesPerRegisterNodes - ns=0;i=11571 */
54525
54526static UA_StatusCode function_namespace0_generated_90_begin(UA_Server *server, UA_UInt16* ns) {
54527UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54528UA_VariableAttributes attr = UA_VariableAttributes_default;
54529attr.minimumSamplingInterval = 0.000000;
54530attr.userAccessLevel = 1;
54531attr.accessLevel = 1;
54532/* Value rank inherited */
54533attr.valueRank = -2;
54534attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54535attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRegisterNodes");
54536retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54537requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11571LU),
54538parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54539referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54540browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRegisterNodes"),
54541typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54542attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54543return retVal;
54544}
54545
54546static UA_StatusCode function_namespace0_generated_90_finish(UA_Server *server, UA_UInt16* ns) {
54547return UA_Server_addNode_finish(server,
54548nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11571LU)
54549);
54550}
54551
54552/* MaxNodesPerBrowse - ns=0;i=11570 */
54553
54554static UA_StatusCode function_namespace0_generated_91_begin(UA_Server *server, UA_UInt16* ns) {
54555UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54556UA_VariableAttributes attr = UA_VariableAttributes_default;
54557attr.minimumSamplingInterval = 0.000000;
54558attr.userAccessLevel = 1;
54559attr.accessLevel = 1;
54560/* Value rank inherited */
54561attr.valueRank = -2;
54562attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54563attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerBrowse");
54564retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54565requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11570LU),
54566parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54567referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54568browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerBrowse"),
54569typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54570attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54571return retVal;
54572}
54573
54574static UA_StatusCode function_namespace0_generated_91_finish(UA_Server *server, UA_UInt16* ns) {
54575return UA_Server_addNode_finish(server,
54576nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11570LU)
54577);
54578}
54579
54580/* MaxNodesPerMethodCall - ns=0;i=11569 */
54581
54582static UA_StatusCode function_namespace0_generated_92_begin(UA_Server *server, UA_UInt16* ns) {
54583UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54584UA_VariableAttributes attr = UA_VariableAttributes_default;
54585attr.minimumSamplingInterval = 0.000000;
54586attr.userAccessLevel = 1;
54587attr.accessLevel = 1;
54588/* Value rank inherited */
54589attr.valueRank = -2;
54590attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54591attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerMethodCall");
54592retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54593requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11569LU),
54594parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54595referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54596browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerMethodCall"),
54597typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54598attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54599return retVal;
54600}
54601
54602static UA_StatusCode function_namespace0_generated_92_finish(UA_Server *server, UA_UInt16* ns) {
54603return UA_Server_addNode_finish(server,
54604nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11569LU)
54605);
54606}
54607
54608/* MaxNodesPerWrite - ns=0;i=11567 */
54609
54610static UA_StatusCode function_namespace0_generated_93_begin(UA_Server *server, UA_UInt16* ns) {
54611UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54612UA_VariableAttributes attr = UA_VariableAttributes_default;
54613attr.minimumSamplingInterval = 0.000000;
54614attr.userAccessLevel = 1;
54615attr.accessLevel = 1;
54616/* Value rank inherited */
54617attr.valueRank = -2;
54618attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54619attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerWrite");
54620retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54621requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11567LU),
54622parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54623referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54624browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerWrite"),
54625typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54626attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54627return retVal;
54628}
54629
54630static UA_StatusCode function_namespace0_generated_93_finish(UA_Server *server, UA_UInt16* ns) {
54631return UA_Server_addNode_finish(server,
54632nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11567LU)
54633);
54634}
54635
54636/* MaxNodesPerRead - ns=0;i=11565 */
54637
54638static UA_StatusCode function_namespace0_generated_94_begin(UA_Server *server, UA_UInt16* ns) {
54639UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54640UA_VariableAttributes attr = UA_VariableAttributes_default;
54641attr.minimumSamplingInterval = 0.000000;
54642attr.userAccessLevel = 1;
54643attr.accessLevel = 1;
54644/* Value rank inherited */
54645attr.valueRank = -2;
54646attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54647attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRead");
54648retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54649requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11565LU),
54650parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54651referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54652browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRead"),
54653typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54654attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54655return retVal;
54656}
54657
54658static UA_StatusCode function_namespace0_generated_94_finish(UA_Server *server, UA_UInt16* ns) {
54659return UA_Server_addNode_finish(server,
54660nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11565LU)
54661);
54662}
54663
54664/* ServerRedundancyType - ns=0;i=2034 */
54665
54666static UA_StatusCode function_namespace0_generated_95_begin(UA_Server *server, UA_UInt16* ns) {
54667UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54668UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54669attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerRedundancyType");
54670retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54671requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU),
54672parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54673referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54674browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerRedundancyType"),
54675 typeDefinition: UA_NODEID_NULL,
54676attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54677return retVal;
54678}
54679
54680static UA_StatusCode function_namespace0_generated_95_finish(UA_Server *server, UA_UInt16* ns) {
54681return UA_Server_addNode_finish(server,
54682nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU)
54683);
54684}
54685
54686/* RedundancySupport - ns=0;i=2035 */
54687
54688static UA_StatusCode function_namespace0_generated_96_begin(UA_Server *server, UA_UInt16* ns) {
54689UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54690UA_VariableAttributes attr = UA_VariableAttributes_default;
54691attr.minimumSamplingInterval = 0.000000;
54692attr.userAccessLevel = 1;
54693attr.accessLevel = 1;
54694/* Value rank inherited */
54695attr.valueRank = -2;
54696attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU);
54697attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport");
54698retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54699requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2035LU),
54700parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU),
54701referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54702browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"),
54703typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54704attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54705return retVal;
54706}
54707
54708static UA_StatusCode function_namespace0_generated_96_finish(UA_Server *server, UA_UInt16* ns) {
54709return UA_Server_addNode_finish(server,
54710nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2035LU)
54711);
54712}
54713
54714/* VendorServerInfoType - ns=0;i=2033 */
54715
54716static UA_StatusCode function_namespace0_generated_97_begin(UA_Server *server, UA_UInt16* ns) {
54717UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54718UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54719attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfoType");
54720retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54721requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU),
54722parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54723referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54724browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfoType"),
54725 typeDefinition: UA_NODEID_NULL,
54726attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54727return retVal;
54728}
54729
54730static UA_StatusCode function_namespace0_generated_97_finish(UA_Server *server, UA_UInt16* ns) {
54731return UA_Server_addNode_finish(server,
54732nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU)
54733);
54734}
54735
54736/* ServerDiagnosticsType - ns=0;i=2020 */
54737
54738static UA_StatusCode function_namespace0_generated_98_begin(UA_Server *server, UA_UInt16* ns) {
54739UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54740UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54741attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnosticsType");
54742retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54743requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU),
54744parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54745referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54746browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnosticsType"),
54747 typeDefinition: UA_NODEID_NULL,
54748attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54749return retVal;
54750}
54751
54752static UA_StatusCode function_namespace0_generated_98_finish(UA_Server *server, UA_UInt16* ns) {
54753return UA_Server_addNode_finish(server,
54754nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU)
54755);
54756}
54757
54758/* ServerCapabilitiesType - ns=0;i=2013 */
54759
54760static UA_StatusCode function_namespace0_generated_99_begin(UA_Server *server, UA_UInt16* ns) {
54761UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54762UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54763attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerCapabilitiesType");
54764retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54765requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU),
54766parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54767referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54768browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerCapabilitiesType"),
54769 typeDefinition: UA_NODEID_NULL,
54770attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54771return retVal;
54772}
54773
54774static UA_StatusCode function_namespace0_generated_99_finish(UA_Server *server, UA_UInt16* ns) {
54775return UA_Server_addNode_finish(server,
54776nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU)
54777);
54778}
54779
54780/* OperationLimits - ns=0;i=11551 */
54781
54782static UA_StatusCode function_namespace0_generated_100_begin(UA_Server *server, UA_UInt16* ns) {
54783UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54784UA_ObjectAttributes attr = UA_ObjectAttributes_default;
54785attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OperationLimits");
54786retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54787requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11551LU),
54788parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU),
54789referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
54790browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimits"),
54791typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54792attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
54793return retVal;
54794}
54795
54796static UA_StatusCode function_namespace0_generated_100_finish(UA_Server *server, UA_UInt16* ns) {
54797return UA_Server_addNode_finish(server,
54798nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11551LU)
54799);
54800}
54801
54802/* ServerType - ns=0;i=2004 */
54803
54804static UA_StatusCode function_namespace0_generated_101_begin(UA_Server *server, UA_UInt16* ns) {
54805UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54806UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54807attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerType");
54808retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54809requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU),
54810parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54811referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54812browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerType"),
54813 typeDefinition: UA_NODEID_NULL,
54814attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54815return retVal;
54816}
54817
54818static UA_StatusCode function_namespace0_generated_101_finish(UA_Server *server, UA_UInt16* ns) {
54819return UA_Server_addNode_finish(server,
54820nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU)
54821);
54822}
54823
54824/* Server - ns=0;i=2253 */
54825
54826static UA_StatusCode function_namespace0_generated_102_begin(UA_Server *server, UA_UInt16* ns) {
54827UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54828UA_ObjectAttributes attr = UA_ObjectAttributes_default;
54829attr.eventNotifier = UA_EVENTNOTIFIER_SUBSCRIBE_TO_EVENT;
54830attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Server");
54831retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54832requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
54833parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 85LU),
54834referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU),
54835browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Server"),
54836typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU),
54837attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
54838return retVal;
54839}
54840
54841static UA_StatusCode function_namespace0_generated_102_finish(UA_Server *server, UA_UInt16* ns) {
54842return UA_Server_addNode_finish(server,
54843nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU)
54844);
54845}
54846
54847/* Auditing - ns=0;i=2994 */
54848
54849static UA_StatusCode function_namespace0_generated_103_begin(UA_Server *server, UA_UInt16* ns) {
54850UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54851UA_VariableAttributes attr = UA_VariableAttributes_default;
54852attr.minimumSamplingInterval = 1000.000000;
54853attr.userAccessLevel = 1;
54854attr.accessLevel = 1;
54855/* Value rank inherited */
54856attr.valueRank = -2;
54857attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
54858attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Auditing");
54859retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54860requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2994LU),
54861parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
54862referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54863browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Auditing"),
54864typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54865attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54866return retVal;
54867}
54868
54869static UA_StatusCode function_namespace0_generated_103_finish(UA_Server *server, UA_UInt16* ns) {
54870return UA_Server_addNode_finish(server,
54871nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2994LU)
54872);
54873}
54874
54875/* ServerRedundancy - ns=0;i=2296 */
54876
54877static UA_StatusCode function_namespace0_generated_104_begin(UA_Server *server, UA_UInt16* ns) {
54878UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54879UA_ObjectAttributes attr = UA_ObjectAttributes_default;
54880attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerRedundancy");
54881retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54882requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU),
54883parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
54884referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
54885browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerRedundancy"),
54886typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU),
54887attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
54888return retVal;
54889}
54890
54891static UA_StatusCode function_namespace0_generated_104_finish(UA_Server *server, UA_UInt16* ns) {
54892return UA_Server_addNode_finish(server,
54893nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU)
54894);
54895}
54896
54897/* RedundancySupport - ns=0;i=3709 */
54898
54899static UA_StatusCode function_namespace0_generated_105_begin(UA_Server *server, UA_UInt16* ns) {
54900UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54901UA_VariableAttributes attr = UA_VariableAttributes_default;
54902attr.minimumSamplingInterval = 0.000000;
54903attr.userAccessLevel = 1;
54904attr.accessLevel = 1;
54905/* Value rank inherited */
54906attr.valueRank = -2;
54907attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU);
54908attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport");
54909retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54910requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3709LU),
54911parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU),
54912referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54913browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"),
54914typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54915attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54916return retVal;
54917}
54918
54919static UA_StatusCode function_namespace0_generated_105_finish(UA_Server *server, UA_UInt16* ns) {
54920return UA_Server_addNode_finish(server,
54921nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3709LU)
54922);
54923}
54924
54925/* VendorServerInfo - ns=0;i=2295 */
54926
54927static UA_StatusCode function_namespace0_generated_106_begin(UA_Server *server, UA_UInt16* ns) {
54928UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54929UA_ObjectAttributes attr = UA_ObjectAttributes_default;
54930attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfo");
54931retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54932requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2295LU),
54933parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
54934referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
54935browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfo"),
54936typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU),
54937attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
54938return retVal;
54939}
54940
54941static UA_StatusCode function_namespace0_generated_106_finish(UA_Server *server, UA_UInt16* ns) {
54942return UA_Server_addNode_finish(server,
54943nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2295LU)
54944);
54945}
54946
54947/* ServerDiagnostics - ns=0;i=2274 */
54948
54949static UA_StatusCode function_namespace0_generated_107_begin(UA_Server *server, UA_UInt16* ns) {
54950UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54951UA_ObjectAttributes attr = UA_ObjectAttributes_default;
54952attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnostics");
54953retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54954requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU),
54955parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
54956referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
54957browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnostics"),
54958typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU),
54959attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
54960return retVal;
54961}
54962
54963static UA_StatusCode function_namespace0_generated_107_finish(UA_Server *server, UA_UInt16* ns) {
54964return UA_Server_addNode_finish(server,
54965nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU)
54966);
54967}
54968
54969/* EnabledFlag - ns=0;i=2294 */
54970
54971static UA_StatusCode function_namespace0_generated_108_begin(UA_Server *server, UA_UInt16* ns) {
54972UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54973UA_VariableAttributes attr = UA_VariableAttributes_default;
54974attr.minimumSamplingInterval = 0.000000;
54975attr.userAccessLevel = 1;
54976attr.accessLevel = 3;
54977/* Value rank inherited */
54978attr.valueRank = -2;
54979attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
54980attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnabledFlag");
54981retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54982requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2294LU),
54983parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU),
54984referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54985browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnabledFlag"),
54986typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54987attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54988return retVal;
54989}
54990
54991static UA_StatusCode function_namespace0_generated_108_finish(UA_Server *server, UA_UInt16* ns) {
54992return UA_Server_addNode_finish(server,
54993nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2294LU)
54994);
54995}
54996
54997/* ServerCapabilities - ns=0;i=2268 */
54998
54999static UA_StatusCode function_namespace0_generated_109_begin(UA_Server *server, UA_UInt16* ns) {
55000UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55001UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55002attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerCapabilities");
55003retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55004requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55005parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55006referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55007browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerCapabilities"),
55008typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU),
55009attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55010return retVal;
55011}
55012
55013static UA_StatusCode function_namespace0_generated_109_finish(UA_Server *server, UA_UInt16* ns) {
55014return UA_Server_addNode_finish(server,
55015nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU)
55016);
55017}
55018
55019/* SoftwareCertificates - ns=0;i=3704 */
55020
55021static UA_StatusCode function_namespace0_generated_110_begin(UA_Server *server, UA_UInt16* ns) {
55022UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55023UA_VariableAttributes attr = UA_VariableAttributes_default;
55024attr.minimumSamplingInterval = 0.000000;
55025attr.userAccessLevel = 1;
55026attr.accessLevel = 1;
55027attr.valueRank = 1;
55028attr.arrayDimensionsSize = 1;
55029UA_UInt32 arrayDimensions[1];
55030arrayDimensions[0] = 0;
55031attr.arrayDimensions = &arrayDimensions[0];
55032attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU);
55033attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SoftwareCertificates");
55034retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55035requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3704LU),
55036parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55037referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55038browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SoftwareCertificates"),
55039typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55040attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55041return retVal;
55042}
55043
55044static UA_StatusCode function_namespace0_generated_110_finish(UA_Server *server, UA_UInt16* ns) {
55045return UA_Server_addNode_finish(server,
55046nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3704LU)
55047);
55048}
55049
55050/* AggregateFunctions - ns=0;i=2997 */
55051
55052static UA_StatusCode function_namespace0_generated_111_begin(UA_Server *server, UA_UInt16* ns) {
55053UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55054UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55055attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AggregateFunctions");
55056retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55057requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2997LU),
55058parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55059referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55060browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AggregateFunctions"),
55061typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
55062attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55063return retVal;
55064}
55065
55066static UA_StatusCode function_namespace0_generated_111_finish(UA_Server *server, UA_UInt16* ns) {
55067return UA_Server_addNode_finish(server,
55068nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2997LU)
55069);
55070}
55071
55072/* ModellingRules - ns=0;i=2996 */
55073
55074static UA_StatusCode function_namespace0_generated_112_begin(UA_Server *server, UA_UInt16* ns) {
55075UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55076UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55077attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModellingRules");
55078retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55079requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2996LU),
55080parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55081referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55082browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModellingRules"),
55083typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
55084attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55085return retVal;
55086}
55087
55088static UA_StatusCode function_namespace0_generated_112_finish(UA_Server *server, UA_UInt16* ns) {
55089return UA_Server_addNode_finish(server,
55090nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2996LU)
55091);
55092}
55093
55094/* MaxHistoryContinuationPoints - ns=0;i=2737 */
55095
55096static UA_StatusCode function_namespace0_generated_113_begin(UA_Server *server, UA_UInt16* ns) {
55097UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55098UA_VariableAttributes attr = UA_VariableAttributes_default;
55099attr.minimumSamplingInterval = 0.000000;
55100attr.userAccessLevel = 1;
55101attr.accessLevel = 1;
55102/* Value rank inherited */
55103attr.valueRank = -2;
55104attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU);
55105attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxHistoryContinuationPoints");
55106retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55107requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2737LU),
55108parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55109referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55110browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxHistoryContinuationPoints"),
55111typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55112attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55113return retVal;
55114}
55115
55116static UA_StatusCode function_namespace0_generated_113_finish(UA_Server *server, UA_UInt16* ns) {
55117return UA_Server_addNode_finish(server,
55118nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2737LU)
55119);
55120}
55121
55122/* MaxQueryContinuationPoints - ns=0;i=2736 */
55123
55124static UA_StatusCode function_namespace0_generated_114_begin(UA_Server *server, UA_UInt16* ns) {
55125UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55126UA_VariableAttributes attr = UA_VariableAttributes_default;
55127attr.minimumSamplingInterval = 0.000000;
55128attr.userAccessLevel = 1;
55129attr.accessLevel = 1;
55130/* Value rank inherited */
55131attr.valueRank = -2;
55132attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU);
55133attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxQueryContinuationPoints");
55134retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55135requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2736LU),
55136parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55137referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55138browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxQueryContinuationPoints"),
55139typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55140attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55141return retVal;
55142}
55143
55144static UA_StatusCode function_namespace0_generated_114_finish(UA_Server *server, UA_UInt16* ns) {
55145return UA_Server_addNode_finish(server,
55146nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2736LU)
55147);
55148}
55149
55150/* MaxBrowseContinuationPoints - ns=0;i=2735 */
55151
55152static UA_StatusCode function_namespace0_generated_115_begin(UA_Server *server, UA_UInt16* ns) {
55153UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55154UA_VariableAttributes attr = UA_VariableAttributes_default;
55155attr.minimumSamplingInterval = 0.000000;
55156attr.userAccessLevel = 1;
55157attr.accessLevel = 1;
55158/* Value rank inherited */
55159attr.valueRank = -2;
55160attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU);
55161attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxBrowseContinuationPoints");
55162retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55163requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2735LU),
55164parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55165referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55166browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxBrowseContinuationPoints"),
55167typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55168attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55169return retVal;
55170}
55171
55172static UA_StatusCode function_namespace0_generated_115_finish(UA_Server *server, UA_UInt16* ns) {
55173return UA_Server_addNode_finish(server,
55174nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2735LU)
55175);
55176}
55177
55178/* MinSupportedSampleRate - ns=0;i=2272 */
55179
55180static UA_StatusCode function_namespace0_generated_116_begin(UA_Server *server, UA_UInt16* ns) {
55181UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55182UA_VariableAttributes attr = UA_VariableAttributes_default;
55183attr.minimumSamplingInterval = 0.000000;
55184attr.userAccessLevel = 1;
55185attr.accessLevel = 1;
55186/* Value rank inherited */
55187attr.valueRank = -2;
55188attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU);
55189attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MinSupportedSampleRate");
55190retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55191requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2272LU),
55192parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55193referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55194browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MinSupportedSampleRate"),
55195typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55196attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55197return retVal;
55198}
55199
55200static UA_StatusCode function_namespace0_generated_116_finish(UA_Server *server, UA_UInt16* ns) {
55201return UA_Server_addNode_finish(server,
55202nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2272LU)
55203);
55204}
55205
55206/* LocaleIdArray - ns=0;i=2271 */
55207
55208static UA_StatusCode function_namespace0_generated_117_begin(UA_Server *server, UA_UInt16* ns) {
55209UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55210UA_VariableAttributes attr = UA_VariableAttributes_default;
55211attr.minimumSamplingInterval = 0.000000;
55212attr.userAccessLevel = 1;
55213attr.accessLevel = 1;
55214attr.valueRank = 1;
55215attr.arrayDimensionsSize = 1;
55216UA_UInt32 arrayDimensions[1];
55217arrayDimensions[0] = 0;
55218attr.arrayDimensions = &arrayDimensions[0];
55219attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU);
55220attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleIdArray");
55221retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55222requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2271LU),
55223parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55224referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55225browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleIdArray"),
55226typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55227attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55228return retVal;
55229}
55230
55231static UA_StatusCode function_namespace0_generated_117_finish(UA_Server *server, UA_UInt16* ns) {
55232return UA_Server_addNode_finish(server,
55233nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2271LU)
55234);
55235}
55236
55237/* ServerProfileArray - ns=0;i=2269 */
55238
55239static UA_StatusCode function_namespace0_generated_118_begin(UA_Server *server, UA_UInt16* ns) {
55240UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55241UA_VariableAttributes attr = UA_VariableAttributes_default;
55242attr.minimumSamplingInterval = 0.000000;
55243attr.userAccessLevel = 1;
55244attr.accessLevel = 1;
55245attr.valueRank = 1;
55246attr.arrayDimensionsSize = 1;
55247UA_UInt32 arrayDimensions[1];
55248arrayDimensions[0] = 0;
55249attr.arrayDimensions = &arrayDimensions[0];
55250attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
55251attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerProfileArray");
55252retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55253requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2269LU),
55254parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55255referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55256browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerProfileArray"),
55257typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55258attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55259return retVal;
55260}
55261
55262static UA_StatusCode function_namespace0_generated_118_finish(UA_Server *server, UA_UInt16* ns) {
55263return UA_Server_addNode_finish(server,
55264nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2269LU)
55265);
55266}
55267
55268/* OperationLimits - ns=0;i=11704 */
55269
55270static UA_StatusCode function_namespace0_generated_119_begin(UA_Server *server, UA_UInt16* ns) {
55271UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55272UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55273attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OperationLimits");
55274retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55275requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55276parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55277referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55278browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimits"),
55279typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
55280attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55281return retVal;
55282}
55283
55284static UA_StatusCode function_namespace0_generated_119_finish(UA_Server *server, UA_UInt16* ns) {
55285return UA_Server_addNode_finish(server,
55286nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU)
55287);
55288}
55289
55290/* MaxMonitoredItemsPerCall - ns=0;i=11714 */
55291
55292static UA_StatusCode function_namespace0_generated_120_begin(UA_Server *server, UA_UInt16* ns) {
55293UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55294UA_VariableAttributes attr = UA_VariableAttributes_default;
55295attr.minimumSamplingInterval = 0.000000;
55296attr.userAccessLevel = 1;
55297attr.accessLevel = 1;
55298/* Value rank inherited */
55299attr.valueRank = -2;
55300attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55301attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxMonitoredItemsPerCall");
55302retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55303requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11714LU),
55304parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55305referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55306browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxMonitoredItemsPerCall"),
55307typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55308attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55309return retVal;
55310}
55311
55312static UA_StatusCode function_namespace0_generated_120_finish(UA_Server *server, UA_UInt16* ns) {
55313return UA_Server_addNode_finish(server,
55314nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11714LU)
55315);
55316}
55317
55318/* MaxNodesPerNodeManagement - ns=0;i=11713 */
55319
55320static UA_StatusCode function_namespace0_generated_121_begin(UA_Server *server, UA_UInt16* ns) {
55321UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55322UA_VariableAttributes attr = UA_VariableAttributes_default;
55323attr.minimumSamplingInterval = 0.000000;
55324attr.userAccessLevel = 1;
55325attr.accessLevel = 1;
55326/* Value rank inherited */
55327attr.valueRank = -2;
55328attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55329attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerNodeManagement");
55330retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55331requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11713LU),
55332parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55333referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55334browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerNodeManagement"),
55335typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55336attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55337return retVal;
55338}
55339
55340static UA_StatusCode function_namespace0_generated_121_finish(UA_Server *server, UA_UInt16* ns) {
55341return UA_Server_addNode_finish(server,
55342nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11713LU)
55343);
55344}
55345
55346/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11712 */
55347
55348static UA_StatusCode function_namespace0_generated_122_begin(UA_Server *server, UA_UInt16* ns) {
55349UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55350UA_VariableAttributes attr = UA_VariableAttributes_default;
55351attr.minimumSamplingInterval = 0.000000;
55352attr.userAccessLevel = 1;
55353attr.accessLevel = 1;
55354/* Value rank inherited */
55355attr.valueRank = -2;
55356attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55357attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerTranslateBrowsePathsToNodeIds");
55358retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55359requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11712LU),
55360parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55361referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55362browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerTranslateBrowsePathsToNodeIds"),
55363typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55364attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55365return retVal;
55366}
55367
55368static UA_StatusCode function_namespace0_generated_122_finish(UA_Server *server, UA_UInt16* ns) {
55369return UA_Server_addNode_finish(server,
55370nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11712LU)
55371);
55372}
55373
55374/* MaxNodesPerRegisterNodes - ns=0;i=11711 */
55375
55376static UA_StatusCode function_namespace0_generated_123_begin(UA_Server *server, UA_UInt16* ns) {
55377UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55378UA_VariableAttributes attr = UA_VariableAttributes_default;
55379attr.minimumSamplingInterval = 0.000000;
55380attr.userAccessLevel = 1;
55381attr.accessLevel = 1;
55382/* Value rank inherited */
55383attr.valueRank = -2;
55384attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55385attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRegisterNodes");
55386retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55387requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11711LU),
55388parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55389referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55390browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRegisterNodes"),
55391typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55392attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55393return retVal;
55394}
55395
55396static UA_StatusCode function_namespace0_generated_123_finish(UA_Server *server, UA_UInt16* ns) {
55397return UA_Server_addNode_finish(server,
55398nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11711LU)
55399);
55400}
55401
55402/* MaxNodesPerBrowse - ns=0;i=11710 */
55403
55404static UA_StatusCode function_namespace0_generated_124_begin(UA_Server *server, UA_UInt16* ns) {
55405UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55406UA_VariableAttributes attr = UA_VariableAttributes_default;
55407attr.minimumSamplingInterval = 0.000000;
55408attr.userAccessLevel = 1;
55409attr.accessLevel = 1;
55410/* Value rank inherited */
55411attr.valueRank = -2;
55412attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55413attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerBrowse");
55414retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55415requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11710LU),
55416parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55417referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55418browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerBrowse"),
55419typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55420attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55421return retVal;
55422}
55423
55424static UA_StatusCode function_namespace0_generated_124_finish(UA_Server *server, UA_UInt16* ns) {
55425return UA_Server_addNode_finish(server,
55426nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11710LU)
55427);
55428}
55429
55430/* MaxNodesPerMethodCall - ns=0;i=11709 */
55431
55432static UA_StatusCode function_namespace0_generated_125_begin(UA_Server *server, UA_UInt16* ns) {
55433UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55434UA_VariableAttributes attr = UA_VariableAttributes_default;
55435attr.minimumSamplingInterval = 0.000000;
55436attr.userAccessLevel = 1;
55437attr.accessLevel = 1;
55438/* Value rank inherited */
55439attr.valueRank = -2;
55440attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55441attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerMethodCall");
55442retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55443requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11709LU),
55444parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55445referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55446browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerMethodCall"),
55447typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55448attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55449return retVal;
55450}
55451
55452static UA_StatusCode function_namespace0_generated_125_finish(UA_Server *server, UA_UInt16* ns) {
55453return UA_Server_addNode_finish(server,
55454nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11709LU)
55455);
55456}
55457
55458/* MaxNodesPerWrite - ns=0;i=11707 */
55459
55460static UA_StatusCode function_namespace0_generated_126_begin(UA_Server *server, UA_UInt16* ns) {
55461UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55462UA_VariableAttributes attr = UA_VariableAttributes_default;
55463attr.minimumSamplingInterval = 0.000000;
55464attr.userAccessLevel = 1;
55465attr.accessLevel = 1;
55466/* Value rank inherited */
55467attr.valueRank = -2;
55468attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55469attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerWrite");
55470retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55471requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11707LU),
55472parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55473referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55474browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerWrite"),
55475typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55476attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55477return retVal;
55478}
55479
55480static UA_StatusCode function_namespace0_generated_126_finish(UA_Server *server, UA_UInt16* ns) {
55481return UA_Server_addNode_finish(server,
55482nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11707LU)
55483);
55484}
55485
55486/* MaxNodesPerRead - ns=0;i=11705 */
55487
55488static UA_StatusCode function_namespace0_generated_127_begin(UA_Server *server, UA_UInt16* ns) {
55489UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55490UA_VariableAttributes attr = UA_VariableAttributes_default;
55491attr.minimumSamplingInterval = 0.000000;
55492attr.userAccessLevel = 1;
55493attr.accessLevel = 1;
55494/* Value rank inherited */
55495attr.valueRank = -2;
55496attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55497attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRead");
55498retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55499requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11705LU),
55500parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55501referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55502browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRead"),
55503typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55504attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55505return retVal;
55506}
55507
55508static UA_StatusCode function_namespace0_generated_127_finish(UA_Server *server, UA_UInt16* ns) {
55509return UA_Server_addNode_finish(server,
55510nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11705LU)
55511);
55512}
55513
55514/* HistoryServerCapabilities - ns=0;i=11192 */
55515
55516static UA_StatusCode function_namespace0_generated_128_begin(UA_Server *server, UA_UInt16* ns) {
55517UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55518UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55519attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryServerCapabilities");
55520retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55521requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55522parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55523referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55524browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryServerCapabilities"),
55525typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU),
55526attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55527return retVal;
55528}
55529
55530static UA_StatusCode function_namespace0_generated_128_finish(UA_Server *server, UA_UInt16* ns) {
55531return UA_Server_addNode_finish(server,
55532nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU)
55533);
55534}
55535
55536/* DeleteEventCapability - ns=0;i=11502 */
55537
55538static UA_StatusCode function_namespace0_generated_129_begin(UA_Server *server, UA_UInt16* ns) {
55539UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55540UA_VariableAttributes attr = UA_VariableAttributes_default;
55541attr.minimumSamplingInterval = 0.000000;
55542attr.userAccessLevel = 1;
55543attr.accessLevel = 1;
55544/* Value rank inherited */
55545attr.valueRank = -2;
55546attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55547attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteEventCapability");
55548retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55549requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11502LU),
55550parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55551referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55552browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteEventCapability"),
55553typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55554attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55555return retVal;
55556}
55557
55558static UA_StatusCode function_namespace0_generated_129_finish(UA_Server *server, UA_UInt16* ns) {
55559return UA_Server_addNode_finish(server,
55560nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11502LU)
55561);
55562}
55563
55564/* UpdateEventCapability - ns=0;i=11283 */
55565
55566static UA_StatusCode function_namespace0_generated_130_begin(UA_Server *server, UA_UInt16* ns) {
55567UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55568UA_VariableAttributes attr = UA_VariableAttributes_default;
55569attr.minimumSamplingInterval = 0.000000;
55570attr.userAccessLevel = 1;
55571attr.accessLevel = 1;
55572/* Value rank inherited */
55573attr.valueRank = -2;
55574attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55575attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UpdateEventCapability");
55576retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55577requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11283LU),
55578parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55579referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55580browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UpdateEventCapability"),
55581typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55582attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55583return retVal;
55584}
55585
55586static UA_StatusCode function_namespace0_generated_130_finish(UA_Server *server, UA_UInt16* ns) {
55587return UA_Server_addNode_finish(server,
55588nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11283LU)
55589);
55590}
55591
55592/* ReplaceEventCapability - ns=0;i=11282 */
55593
55594static UA_StatusCode function_namespace0_generated_131_begin(UA_Server *server, UA_UInt16* ns) {
55595UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55596UA_VariableAttributes attr = UA_VariableAttributes_default;
55597attr.minimumSamplingInterval = 0.000000;
55598attr.userAccessLevel = 1;
55599attr.accessLevel = 1;
55600/* Value rank inherited */
55601attr.valueRank = -2;
55602attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55603attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReplaceEventCapability");
55604retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55605requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11282LU),
55606parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55607referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55608browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReplaceEventCapability"),
55609typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55610attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55611return retVal;
55612}
55613
55614static UA_StatusCode function_namespace0_generated_131_finish(UA_Server *server, UA_UInt16* ns) {
55615return UA_Server_addNode_finish(server,
55616nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11282LU)
55617);
55618}
55619
55620/* InsertEventCapability - ns=0;i=11281 */
55621
55622static UA_StatusCode function_namespace0_generated_132_begin(UA_Server *server, UA_UInt16* ns) {
55623UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55624UA_VariableAttributes attr = UA_VariableAttributes_default;
55625attr.minimumSamplingInterval = 0.000000;
55626attr.userAccessLevel = 1;
55627attr.accessLevel = 1;
55628/* Value rank inherited */
55629attr.valueRank = -2;
55630attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55631attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertEventCapability");
55632retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55633requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11281LU),
55634parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55635referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55636browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertEventCapability"),
55637typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55638attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55639return retVal;
55640}
55641
55642static UA_StatusCode function_namespace0_generated_132_finish(UA_Server *server, UA_UInt16* ns) {
55643return UA_Server_addNode_finish(server,
55644nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11281LU)
55645);
55646}
55647
55648/* InsertAnnotationCapability - ns=0;i=11275 */
55649
55650static UA_StatusCode function_namespace0_generated_133_begin(UA_Server *server, UA_UInt16* ns) {
55651UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55652UA_VariableAttributes attr = UA_VariableAttributes_default;
55653attr.minimumSamplingInterval = 0.000000;
55654attr.userAccessLevel = 1;
55655attr.accessLevel = 1;
55656/* Value rank inherited */
55657attr.valueRank = -2;
55658attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55659attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertAnnotationCapability");
55660retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55661requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11275LU),
55662parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55663referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55664browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertAnnotationCapability"),
55665typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55666attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55667return retVal;
55668}
55669
55670static UA_StatusCode function_namespace0_generated_133_finish(UA_Server *server, UA_UInt16* ns) {
55671return UA_Server_addNode_finish(server,
55672nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11275LU)
55673);
55674}
55675
55676/* MaxReturnEventValues - ns=0;i=11274 */
55677
55678static UA_StatusCode function_namespace0_generated_134_begin(UA_Server *server, UA_UInt16* ns) {
55679UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55680UA_VariableAttributes attr = UA_VariableAttributes_default;
55681attr.minimumSamplingInterval = 0.000000;
55682attr.userAccessLevel = 1;
55683attr.accessLevel = 1;
55684/* Value rank inherited */
55685attr.valueRank = -2;
55686attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55687attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxReturnEventValues");
55688retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55689requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11274LU),
55690parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55691referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55692browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxReturnEventValues"),
55693typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55694attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55695return retVal;
55696}
55697
55698static UA_StatusCode function_namespace0_generated_134_finish(UA_Server *server, UA_UInt16* ns) {
55699return UA_Server_addNode_finish(server,
55700nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11274LU)
55701);
55702}
55703
55704/* MaxReturnDataValues - ns=0;i=11273 */
55705
55706static UA_StatusCode function_namespace0_generated_135_begin(UA_Server *server, UA_UInt16* ns) {
55707UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55708UA_VariableAttributes attr = UA_VariableAttributes_default;
55709attr.minimumSamplingInterval = 0.000000;
55710attr.userAccessLevel = 1;
55711attr.accessLevel = 1;
55712/* Value rank inherited */
55713attr.valueRank = -2;
55714attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55715attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxReturnDataValues");
55716retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55717requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11273LU),
55718parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55719referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55720browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxReturnDataValues"),
55721typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55722attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55723return retVal;
55724}
55725
55726static UA_StatusCode function_namespace0_generated_135_finish(UA_Server *server, UA_UInt16* ns) {
55727return UA_Server_addNode_finish(server,
55728nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11273LU)
55729);
55730}
55731
55732/* AccessHistoryEventsCapability - ns=0;i=11242 */
55733
55734static UA_StatusCode function_namespace0_generated_136_begin(UA_Server *server, UA_UInt16* ns) {
55735UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55736UA_VariableAttributes attr = UA_VariableAttributes_default;
55737attr.minimumSamplingInterval = 0.000000;
55738attr.userAccessLevel = 1;
55739attr.accessLevel = 1;
55740/* Value rank inherited */
55741attr.valueRank = -2;
55742attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55743attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AccessHistoryEventsCapability");
55744retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55745requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11242LU),
55746parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55747referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55748browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AccessHistoryEventsCapability"),
55749typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55750attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55751return retVal;
55752}
55753
55754static UA_StatusCode function_namespace0_generated_136_finish(UA_Server *server, UA_UInt16* ns) {
55755return UA_Server_addNode_finish(server,
55756nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11242LU)
55757);
55758}
55759
55760/* AggregateFunctions - ns=0;i=11201 */
55761
55762static UA_StatusCode function_namespace0_generated_137_begin(UA_Server *server, UA_UInt16* ns) {
55763UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55764UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55765attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AggregateFunctions");
55766retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55767requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11201LU),
55768parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55769referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55770browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AggregateFunctions"),
55771typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
55772attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55773return retVal;
55774}
55775
55776static UA_StatusCode function_namespace0_generated_137_finish(UA_Server *server, UA_UInt16* ns) {
55777return UA_Server_addNode_finish(server,
55778nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11201LU)
55779);
55780}
55781
55782/* DeleteAtTimeCapability - ns=0;i=11200 */
55783
55784static UA_StatusCode function_namespace0_generated_138_begin(UA_Server *server, UA_UInt16* ns) {
55785UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55786UA_VariableAttributes attr = UA_VariableAttributes_default;
55787attr.minimumSamplingInterval = 0.000000;
55788attr.userAccessLevel = 1;
55789attr.accessLevel = 1;
55790/* Value rank inherited */
55791attr.valueRank = -2;
55792attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55793attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteAtTimeCapability");
55794retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55795requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11200LU),
55796parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55797referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55798browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteAtTimeCapability"),
55799typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55800attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55801return retVal;
55802}
55803
55804static UA_StatusCode function_namespace0_generated_138_finish(UA_Server *server, UA_UInt16* ns) {
55805return UA_Server_addNode_finish(server,
55806nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11200LU)
55807);
55808}
55809
55810/* DeleteRawCapability - ns=0;i=11199 */
55811
55812static UA_StatusCode function_namespace0_generated_139_begin(UA_Server *server, UA_UInt16* ns) {
55813UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55814UA_VariableAttributes attr = UA_VariableAttributes_default;
55815attr.minimumSamplingInterval = 0.000000;
55816attr.userAccessLevel = 1;
55817attr.accessLevel = 1;
55818/* Value rank inherited */
55819attr.valueRank = -2;
55820attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55821attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteRawCapability");
55822retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55823requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11199LU),
55824parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55825referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55826browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteRawCapability"),
55827typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55828attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55829return retVal;
55830}
55831
55832static UA_StatusCode function_namespace0_generated_139_finish(UA_Server *server, UA_UInt16* ns) {
55833return UA_Server_addNode_finish(server,
55834nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11199LU)
55835);
55836}
55837
55838/* UpdateDataCapability - ns=0;i=11198 */
55839
55840static UA_StatusCode function_namespace0_generated_140_begin(UA_Server *server, UA_UInt16* ns) {
55841UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55842UA_VariableAttributes attr = UA_VariableAttributes_default;
55843attr.minimumSamplingInterval = 0.000000;
55844attr.userAccessLevel = 1;
55845attr.accessLevel = 1;
55846/* Value rank inherited */
55847attr.valueRank = -2;
55848attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55849attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UpdateDataCapability");
55850retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55851requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11198LU),
55852parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55853referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55854browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UpdateDataCapability"),
55855typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55856attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55857return retVal;
55858}
55859
55860static UA_StatusCode function_namespace0_generated_140_finish(UA_Server *server, UA_UInt16* ns) {
55861return UA_Server_addNode_finish(server,
55862nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11198LU)
55863);
55864}
55865
55866/* ReplaceDataCapability - ns=0;i=11197 */
55867
55868static UA_StatusCode function_namespace0_generated_141_begin(UA_Server *server, UA_UInt16* ns) {
55869UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55870UA_VariableAttributes attr = UA_VariableAttributes_default;
55871attr.minimumSamplingInterval = 0.000000;
55872attr.userAccessLevel = 1;
55873attr.accessLevel = 1;
55874/* Value rank inherited */
55875attr.valueRank = -2;
55876attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55877attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReplaceDataCapability");
55878retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55879requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11197LU),
55880parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55881referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55882browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReplaceDataCapability"),
55883typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55884attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55885return retVal;
55886}
55887
55888static UA_StatusCode function_namespace0_generated_141_finish(UA_Server *server, UA_UInt16* ns) {
55889return UA_Server_addNode_finish(server,
55890nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11197LU)
55891);
55892}
55893
55894/* InsertDataCapability - ns=0;i=11196 */
55895
55896static UA_StatusCode function_namespace0_generated_142_begin(UA_Server *server, UA_UInt16* ns) {
55897UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55898UA_VariableAttributes attr = UA_VariableAttributes_default;
55899attr.minimumSamplingInterval = 0.000000;
55900attr.userAccessLevel = 1;
55901attr.accessLevel = 1;
55902/* Value rank inherited */
55903attr.valueRank = -2;
55904attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55905attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertDataCapability");
55906retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55907requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11196LU),
55908parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55909referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55910browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertDataCapability"),
55911typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55912attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55913return retVal;
55914}
55915
55916static UA_StatusCode function_namespace0_generated_142_finish(UA_Server *server, UA_UInt16* ns) {
55917return UA_Server_addNode_finish(server,
55918nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11196LU)
55919);
55920}
55921
55922/* AccessHistoryDataCapability - ns=0;i=11193 */
55923
55924static UA_StatusCode function_namespace0_generated_143_begin(UA_Server *server, UA_UInt16* ns) {
55925UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55926UA_VariableAttributes attr = UA_VariableAttributes_default;
55927attr.minimumSamplingInterval = 0.000000;
55928attr.userAccessLevel = 1;
55929attr.accessLevel = 1;
55930/* Value rank inherited */
55931attr.valueRank = -2;
55932attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55933attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AccessHistoryDataCapability");
55934retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55935requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11193LU),
55936parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55937referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55938browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AccessHistoryDataCapability"),
55939typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55940attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55941return retVal;
55942}
55943
55944static UA_StatusCode function_namespace0_generated_143_finish(UA_Server *server, UA_UInt16* ns) {
55945return UA_Server_addNode_finish(server,
55946nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11193LU)
55947);
55948}
55949
55950/* ServiceLevel - ns=0;i=2267 */
55951
55952static UA_StatusCode function_namespace0_generated_144_begin(UA_Server *server, UA_UInt16* ns) {
55953UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55954UA_VariableAttributes attr = UA_VariableAttributes_default;
55955attr.minimumSamplingInterval = 1000.000000;
55956attr.userAccessLevel = 1;
55957attr.accessLevel = 1;
55958/* Value rank inherited */
55959attr.valueRank = -2;
55960attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU);
55961attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServiceLevel");
55962retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55963requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2267LU),
55964parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55965referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55966browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServiceLevel"),
55967typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55968attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55969return retVal;
55970}
55971
55972static UA_StatusCode function_namespace0_generated_144_finish(UA_Server *server, UA_UInt16* ns) {
55973return UA_Server_addNode_finish(server,
55974nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2267LU)
55975);
55976}
55977
55978/* ServerStatus - ns=0;i=2256 */
55979
55980static UA_StatusCode function_namespace0_generated_145_begin(UA_Server *server, UA_UInt16* ns) {
55981UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55982UA_VariableAttributes attr = UA_VariableAttributes_default;
55983attr.minimumSamplingInterval = 1000.000000;
55984attr.userAccessLevel = 1;
55985attr.accessLevel = 1;
55986/* Value rank inherited */
55987attr.valueRank = -2;
55988attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU);
55989attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatus");
55990retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55991requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
55992parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55993referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55994browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatus"),
55995typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU),
55996attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55997return retVal;
55998}
55999
56000static UA_StatusCode function_namespace0_generated_145_finish(UA_Server *server, UA_UInt16* ns) {
56001return UA_Server_addNode_finish(server,
56002nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU)
56003);
56004}
56005
56006/* ShutdownReason - ns=0;i=2993 */
56007
56008static UA_StatusCode function_namespace0_generated_146_begin(UA_Server *server, UA_UInt16* ns) {
56009UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56010UA_VariableAttributes attr = UA_VariableAttributes_default;
56011attr.minimumSamplingInterval = 0.000000;
56012attr.userAccessLevel = 1;
56013attr.accessLevel = 1;
56014/* Value rank inherited */
56015attr.valueRank = -2;
56016attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
56017attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ShutdownReason");
56018retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56019requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2993LU),
56020parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56021referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56022browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ShutdownReason"),
56023typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56024attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56025return retVal;
56026}
56027
56028static UA_StatusCode function_namespace0_generated_146_finish(UA_Server *server, UA_UInt16* ns) {
56029return UA_Server_addNode_finish(server,
56030nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2993LU)
56031);
56032}
56033
56034/* SecondsTillShutdown - ns=0;i=2992 */
56035
56036static UA_StatusCode function_namespace0_generated_147_begin(UA_Server *server, UA_UInt16* ns) {
56037UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56038UA_VariableAttributes attr = UA_VariableAttributes_default;
56039attr.minimumSamplingInterval = 0.000000;
56040attr.userAccessLevel = 1;
56041attr.accessLevel = 1;
56042/* Value rank inherited */
56043attr.valueRank = -2;
56044attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
56045attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecondsTillShutdown");
56046retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56047requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2992LU),
56048parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56049referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56050browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecondsTillShutdown"),
56051typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56052attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56053return retVal;
56054}
56055
56056static UA_StatusCode function_namespace0_generated_147_finish(UA_Server *server, UA_UInt16* ns) {
56057return UA_Server_addNode_finish(server,
56058nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2992LU)
56059);
56060}
56061
56062/* BuildInfo - ns=0;i=2260 */
56063
56064static UA_StatusCode function_namespace0_generated_148_begin(UA_Server *server, UA_UInt16* ns) {
56065UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56066UA_VariableAttributes attr = UA_VariableAttributes_default;
56067attr.minimumSamplingInterval = 0.000000;
56068attr.userAccessLevel = 1;
56069attr.accessLevel = 1;
56070/* Value rank inherited */
56071attr.valueRank = -2;
56072attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU);
56073attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfo");
56074retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56075requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56076parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56077referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56078browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfo"),
56079typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU),
56080attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56081return retVal;
56082}
56083
56084static UA_StatusCode function_namespace0_generated_148_finish(UA_Server *server, UA_UInt16* ns) {
56085return UA_Server_addNode_finish(server,
56086nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU)
56087);
56088}
56089
56090/* BuildDate - ns=0;i=2266 */
56091
56092static UA_StatusCode function_namespace0_generated_149_begin(UA_Server *server, UA_UInt16* ns) {
56093UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56094UA_VariableAttributes attr = UA_VariableAttributes_default;
56095attr.minimumSamplingInterval = 1000.000000;
56096attr.userAccessLevel = 1;
56097attr.accessLevel = 1;
56098/* Value rank inherited */
56099attr.valueRank = -2;
56100attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
56101attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildDate");
56102retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56103requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2266LU),
56104parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56105referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56106browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildDate"),
56107typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56108attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56109return retVal;
56110}
56111
56112static UA_StatusCode function_namespace0_generated_149_finish(UA_Server *server, UA_UInt16* ns) {
56113return UA_Server_addNode_finish(server,
56114nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2266LU)
56115);
56116}
56117
56118/* BuildNumber - ns=0;i=2265 */
56119
56120static UA_StatusCode function_namespace0_generated_150_begin(UA_Server *server, UA_UInt16* ns) {
56121UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56122UA_VariableAttributes attr = UA_VariableAttributes_default;
56123attr.minimumSamplingInterval = 1000.000000;
56124attr.userAccessLevel = 1;
56125attr.accessLevel = 1;
56126/* Value rank inherited */
56127attr.valueRank = -2;
56128attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56129attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildNumber");
56130retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56131requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2265LU),
56132parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56133referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56134browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildNumber"),
56135typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56136attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56137return retVal;
56138}
56139
56140static UA_StatusCode function_namespace0_generated_150_finish(UA_Server *server, UA_UInt16* ns) {
56141return UA_Server_addNode_finish(server,
56142nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2265LU)
56143);
56144}
56145
56146/* SoftwareVersion - ns=0;i=2264 */
56147
56148static UA_StatusCode function_namespace0_generated_151_begin(UA_Server *server, UA_UInt16* ns) {
56149UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56150UA_VariableAttributes attr = UA_VariableAttributes_default;
56151attr.minimumSamplingInterval = 1000.000000;
56152attr.userAccessLevel = 1;
56153attr.accessLevel = 1;
56154/* Value rank inherited */
56155attr.valueRank = -2;
56156attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56157attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SoftwareVersion");
56158retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56159requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2264LU),
56160parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56161referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56162browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SoftwareVersion"),
56163typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56164attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56165return retVal;
56166}
56167
56168static UA_StatusCode function_namespace0_generated_151_finish(UA_Server *server, UA_UInt16* ns) {
56169return UA_Server_addNode_finish(server,
56170nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2264LU)
56171);
56172}
56173
56174/* ManufacturerName - ns=0;i=2263 */
56175
56176static UA_StatusCode function_namespace0_generated_152_begin(UA_Server *server, UA_UInt16* ns) {
56177UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56178UA_VariableAttributes attr = UA_VariableAttributes_default;
56179attr.minimumSamplingInterval = 1000.000000;
56180attr.userAccessLevel = 1;
56181attr.accessLevel = 1;
56182/* Value rank inherited */
56183attr.valueRank = -2;
56184attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56185attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ManufacturerName");
56186retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56187requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2263LU),
56188parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56189referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56190browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ManufacturerName"),
56191typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56192attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56193return retVal;
56194}
56195
56196static UA_StatusCode function_namespace0_generated_152_finish(UA_Server *server, UA_UInt16* ns) {
56197return UA_Server_addNode_finish(server,
56198nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2263LU)
56199);
56200}
56201
56202/* ProductUri - ns=0;i=2262 */
56203
56204static UA_StatusCode function_namespace0_generated_153_begin(UA_Server *server, UA_UInt16* ns) {
56205UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56206UA_VariableAttributes attr = UA_VariableAttributes_default;
56207attr.minimumSamplingInterval = 1000.000000;
56208attr.userAccessLevel = 1;
56209attr.accessLevel = 1;
56210/* Value rank inherited */
56211attr.valueRank = -2;
56212attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56213attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ProductUri");
56214retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56215requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2262LU),
56216parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56217referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56218browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ProductUri"),
56219typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56220attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56221return retVal;
56222}
56223
56224static UA_StatusCode function_namespace0_generated_153_finish(UA_Server *server, UA_UInt16* ns) {
56225return UA_Server_addNode_finish(server,
56226nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2262LU)
56227);
56228}
56229
56230/* ProductName - ns=0;i=2261 */
56231
56232static UA_StatusCode function_namespace0_generated_154_begin(UA_Server *server, UA_UInt16* ns) {
56233UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56234UA_VariableAttributes attr = UA_VariableAttributes_default;
56235attr.minimumSamplingInterval = 1000.000000;
56236attr.userAccessLevel = 1;
56237attr.accessLevel = 1;
56238/* Value rank inherited */
56239attr.valueRank = -2;
56240attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56241attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ProductName");
56242retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56243requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2261LU),
56244parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56245referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56246browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ProductName"),
56247typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56248attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56249return retVal;
56250}
56251
56252static UA_StatusCode function_namespace0_generated_154_finish(UA_Server *server, UA_UInt16* ns) {
56253return UA_Server_addNode_finish(server,
56254nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2261LU)
56255);
56256}
56257
56258/* State - ns=0;i=2259 */
56259
56260static UA_StatusCode function_namespace0_generated_155_begin(UA_Server *server, UA_UInt16* ns) {
56261UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56262UA_VariableAttributes attr = UA_VariableAttributes_default;
56263attr.minimumSamplingInterval = 0.000000;
56264attr.userAccessLevel = 1;
56265attr.accessLevel = 1;
56266/* Value rank inherited */
56267attr.valueRank = -2;
56268attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU);
56269attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "State");
56270retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56271requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2259LU),
56272parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56273referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56274browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "State"),
56275typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56276attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56277return retVal;
56278}
56279
56280static UA_StatusCode function_namespace0_generated_155_finish(UA_Server *server, UA_UInt16* ns) {
56281return UA_Server_addNode_finish(server,
56282nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2259LU)
56283);
56284}
56285
56286/* CurrentTime - ns=0;i=2258 */
56287
56288static UA_StatusCode function_namespace0_generated_156_begin(UA_Server *server, UA_UInt16* ns) {
56289UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56290UA_VariableAttributes attr = UA_VariableAttributes_default;
56291attr.minimumSamplingInterval = 0.000000;
56292attr.userAccessLevel = 1;
56293attr.accessLevel = 1;
56294/* Value rank inherited */
56295attr.valueRank = -2;
56296attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
56297attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentTime");
56298retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56299requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2258LU),
56300parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56301referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56302browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentTime"),
56303typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56304attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56305return retVal;
56306}
56307
56308static UA_StatusCode function_namespace0_generated_156_finish(UA_Server *server, UA_UInt16* ns) {
56309return UA_Server_addNode_finish(server,
56310nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2258LU)
56311);
56312}
56313
56314/* StartTime - ns=0;i=2257 */
56315
56316static UA_StatusCode function_namespace0_generated_157_begin(UA_Server *server, UA_UInt16* ns) {
56317UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56318UA_VariableAttributes attr = UA_VariableAttributes_default;
56319attr.minimumSamplingInterval = 0.000000;
56320attr.userAccessLevel = 1;
56321attr.accessLevel = 1;
56322/* Value rank inherited */
56323attr.valueRank = -2;
56324attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
56325attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "StartTime");
56326retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56327requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2257LU),
56328parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56329referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56330browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "StartTime"),
56331typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56332attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56333return retVal;
56334}
56335
56336static UA_StatusCode function_namespace0_generated_157_finish(UA_Server *server, UA_UInt16* ns) {
56337return UA_Server_addNode_finish(server,
56338nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2257LU)
56339);
56340}
56341
56342/* NamespaceArray - ns=0;i=2255 */
56343
56344static UA_StatusCode function_namespace0_generated_158_begin(UA_Server *server, UA_UInt16* ns) {
56345UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56346UA_VariableAttributes attr = UA_VariableAttributes_default;
56347attr.minimumSamplingInterval = 1000.000000;
56348attr.userAccessLevel = 1;
56349attr.accessLevel = 1;
56350attr.valueRank = 1;
56351attr.arrayDimensionsSize = 1;
56352UA_UInt32 arrayDimensions[1];
56353arrayDimensions[0] = 0;
56354attr.arrayDimensions = &arrayDimensions[0];
56355attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56356attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamespaceArray");
56357retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56358requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2255LU),
56359parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
56360referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56361browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamespaceArray"),
56362typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56363attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56364return retVal;
56365}
56366
56367static UA_StatusCode function_namespace0_generated_158_finish(UA_Server *server, UA_UInt16* ns) {
56368return UA_Server_addNode_finish(server,
56369nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2255LU)
56370);
56371}
56372
56373/* ServerArray - ns=0;i=2254 */
56374
56375static UA_StatusCode function_namespace0_generated_159_begin(UA_Server *server, UA_UInt16* ns) {
56376UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56377UA_VariableAttributes attr = UA_VariableAttributes_default;
56378attr.minimumSamplingInterval = 1000.000000;
56379attr.userAccessLevel = 1;
56380attr.accessLevel = 1;
56381attr.valueRank = 1;
56382attr.arrayDimensionsSize = 1;
56383UA_UInt32 arrayDimensions[1];
56384arrayDimensions[0] = 0;
56385attr.arrayDimensions = &arrayDimensions[0];
56386attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56387attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerArray");
56388retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56389requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2254LU),
56390parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
56391referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56392browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerArray"),
56393typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56394attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56395return retVal;
56396}
56397
56398static UA_StatusCode function_namespace0_generated_159_finish(UA_Server *server, UA_UInt16* ns) {
56399return UA_Server_addNode_finish(server,
56400nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2254LU)
56401);
56402}
56403
56404/* GetMonitoredItems - ns=0;i=11492 */
56405
56406static UA_StatusCode function_namespace0_generated_160_begin(UA_Server *server, UA_UInt16* ns) {
56407#ifdef UA_ENABLE_METHODCALLS
56408UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56409UA_MethodAttributes attr = UA_MethodAttributes_default;
56410attr.executable = true;
56411attr.userExecutable = true;
56412attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "GetMonitoredItems");
56413retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD,
56414requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU),
56415parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
56416referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56417browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "GetMonitoredItems"),
56418 typeDefinition: UA_NODEID_NULL,
56419attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL);
56420return retVal;
56421#else
56422return UA_STATUSCODE_GOOD;
56423#endif /* UA_ENABLE_METHODCALLS */
56424}
56425
56426static UA_StatusCode function_namespace0_generated_160_finish(UA_Server *server, UA_UInt16* ns) {
56427#ifdef UA_ENABLE_METHODCALLS
56428return UA_Server_addMethodNode_finish(server,
56429nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU)
56430, NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL);
56431#else
56432return UA_STATUSCODE_GOOD;
56433#endif /* UA_ENABLE_METHODCALLS */
56434}
56435
56436/* OutputArguments - ns=0;i=11494 */
56437
56438static UA_StatusCode function_namespace0_generated_161_begin(UA_Server *server, UA_UInt16* ns) {
56439#ifdef UA_ENABLE_METHODCALLS
56440UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56441UA_VariableAttributes attr = UA_VariableAttributes_default;
56442attr.minimumSamplingInterval = 0.000000;
56443attr.userAccessLevel = 1;
56444attr.accessLevel = 1;
56445attr.valueRank = 1;
56446attr.arrayDimensionsSize = 1;
56447UA_UInt32 arrayDimensions[1];
56448arrayDimensions[0] = 0;
56449attr.arrayDimensions = &arrayDimensions[0];
56450attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU);
56451UA_Argument variablenode_ns_0_i_11494_variant_DataContents[2];
56452
56453UA_init(p: &variablenode_ns_0_i_11494_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56454variablenode_ns_0_i_11494_variant_DataContents[0].name = UA_STRING(chars: "ServerHandles");
56455variablenode_ns_0_i_11494_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
56456variablenode_ns_0_i_11494_variant_DataContents[0].valueRank = (UA_Int32) 1;
56457UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, 1);
56458UA_init(p: variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]);
56459variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions[0] = (UA_UInt32) 0;
56460variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensionsSize = 1;
56461variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions;
56462
56463UA_init(p: &variablenode_ns_0_i_11494_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56464variablenode_ns_0_i_11494_variant_DataContents[1].name = UA_STRING(chars: "ClientHandles");
56465variablenode_ns_0_i_11494_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
56466variablenode_ns_0_i_11494_variant_DataContents[1].valueRank = (UA_Int32) 1;
56467UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, 1);
56468UA_init(p: variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]);
56469variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions[0] = (UA_UInt32) 0;
56470variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensionsSize = 1;
56471variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions;
56472UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_11494_variant_DataContents, arraySize: (UA_Int32) 2, type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56473attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments");
56474retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56475requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11494LU),
56476parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU),
56477referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56478browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"),
56479typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56480attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56481
56482
56483return retVal;
56484#else
56485return UA_STATUSCODE_GOOD;
56486#endif /* UA_ENABLE_METHODCALLS */
56487}
56488
56489static UA_StatusCode function_namespace0_generated_161_finish(UA_Server *server, UA_UInt16* ns) {
56490#ifdef UA_ENABLE_METHODCALLS
56491return UA_Server_addNode_finish(server,
56492nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11494LU)
56493);
56494#else
56495return UA_STATUSCODE_GOOD;
56496#endif /* UA_ENABLE_METHODCALLS */
56497}
56498
56499/* InputArguments - ns=0;i=11493 */
56500
56501static UA_StatusCode function_namespace0_generated_162_begin(UA_Server *server, UA_UInt16* ns) {
56502#ifdef UA_ENABLE_METHODCALLS
56503UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56504UA_VariableAttributes attr = UA_VariableAttributes_default;
56505attr.minimumSamplingInterval = 0.000000;
56506attr.userAccessLevel = 1;
56507attr.accessLevel = 1;
56508attr.valueRank = 1;
56509attr.arrayDimensionsSize = 1;
56510UA_UInt32 arrayDimensions[1];
56511arrayDimensions[0] = 0;
56512attr.arrayDimensions = &arrayDimensions[0];
56513attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU);
56514UA_Argument variablenode_ns_0_i_11493_variant_DataContents[1];
56515
56516UA_init(p: &variablenode_ns_0_i_11493_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56517variablenode_ns_0_i_11493_variant_DataContents[0].name = UA_STRING(chars: "SubscriptionId");
56518variablenode_ns_0_i_11493_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
56519variablenode_ns_0_i_11493_variant_DataContents[0].valueRank = (UA_Int32) -1;
56520UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_11493_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56521attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments");
56522retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56523requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11493LU),
56524parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU),
56525referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56526browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"),
56527typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56528attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56529
56530return retVal;
56531#else
56532return UA_STATUSCODE_GOOD;
56533#endif /* UA_ENABLE_METHODCALLS */
56534}
56535
56536static UA_StatusCode function_namespace0_generated_162_finish(UA_Server *server, UA_UInt16* ns) {
56537#ifdef UA_ENABLE_METHODCALLS
56538return UA_Server_addNode_finish(server,
56539nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11493LU)
56540);
56541#else
56542return UA_STATUSCODE_GOOD;
56543#endif /* UA_ENABLE_METHODCALLS */
56544}
56545
56546/* VendorServerInfo - ns=0;i=2011 */
56547
56548static UA_StatusCode function_namespace0_generated_163_begin(UA_Server *server, UA_UInt16* ns) {
56549UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56550UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56551attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfo");
56552retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56553requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2011LU),
56554parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU),
56555referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56556browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfo"),
56557typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU),
56558attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56559return retVal;
56560}
56561
56562static UA_StatusCode function_namespace0_generated_163_finish(UA_Server *server, UA_UInt16* ns) {
56563return UA_Server_addNode_finish(server,
56564nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2011LU)
56565);
56566}
56567
56568/* ModellingRuleType - ns=0;i=77 */
56569
56570static UA_StatusCode function_namespace0_generated_164_begin(UA_Server *server, UA_UInt16* ns) {
56571UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56572UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
56573attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModellingRuleType");
56574retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
56575requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56576parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
56577referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
56578browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModellingRuleType"),
56579 typeDefinition: UA_NODEID_NULL,
56580attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
56581return retVal;
56582}
56583
56584static UA_StatusCode function_namespace0_generated_164_finish(UA_Server *server, UA_UInt16* ns) {
56585return UA_Server_addNode_finish(server,
56586nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU)
56587);
56588}
56589
56590/* ExposesItsArray - ns=0;i=83 */
56591
56592static UA_StatusCode function_namespace0_generated_165_begin(UA_Server *server, UA_UInt16* ns) {
56593UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56594UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56595attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ExposesItsArray");
56596retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56597requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU),
56598parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56599referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56600browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ExposesItsArray"),
56601typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56602attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56603return retVal;
56604}
56605
56606static UA_StatusCode function_namespace0_generated_165_finish(UA_Server *server, UA_UInt16* ns) {
56607return UA_Server_addNode_finish(server,
56608nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU)
56609);
56610}
56611
56612/* NamingRule - ns=0;i=114 */
56613
56614static UA_StatusCode function_namespace0_generated_166_begin(UA_Server *server, UA_UInt16* ns) {
56615UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56616UA_VariableAttributes attr = UA_VariableAttributes_default;
56617attr.minimumSamplingInterval = 0.000000;
56618attr.userAccessLevel = 1;
56619attr.accessLevel = 1;
56620/* Value rank inherited */
56621attr.valueRank = -2;
56622attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56623UA_Int32 *variablenode_ns_0_i_114_variant_DataContents = UA_Int32_new();
56624if (!variablenode_ns_0_i_114_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56625UA_Int32_init(p: variablenode_ns_0_i_114_variant_DataContents);
56626*variablenode_ns_0_i_114_variant_DataContents = (UA_Int32) 3;
56627UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_114_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56628attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56629retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56630requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 114LU),
56631parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU),
56632referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56633browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56634typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56635attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56636UA_Int32_delete(p: variablenode_ns_0_i_114_variant_DataContents);
56637return retVal;
56638}
56639
56640static UA_StatusCode function_namespace0_generated_166_finish(UA_Server *server, UA_UInt16* ns) {
56641return UA_Server_addNode_finish(server,
56642nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 114LU)
56643);
56644}
56645
56646/* Optional - ns=0;i=80 */
56647
56648static UA_StatusCode function_namespace0_generated_167_begin(UA_Server *server, UA_UInt16* ns) {
56649UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56650UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56651attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Optional");
56652retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56653requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU),
56654parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56655referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56656browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Optional"),
56657typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56658attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56659retVal |= 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);
56660retVal |= 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);
56661retVal |= 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);
56662retVal |= 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);
56663retVal |= 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);
56664retVal |= 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);
56665retVal |= 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);
56666retVal |= 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);
56667retVal |= 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);
56668retVal |= 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);
56669retVal |= 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);
56670retVal |= 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);
56671retVal |= 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);
56672retVal |= 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);
56673return retVal;
56674}
56675
56676static UA_StatusCode function_namespace0_generated_167_finish(UA_Server *server, UA_UInt16* ns) {
56677return UA_Server_addNode_finish(server,
56678nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU)
56679);
56680}
56681
56682/* NamingRule - ns=0;i=113 */
56683
56684static UA_StatusCode function_namespace0_generated_168_begin(UA_Server *server, UA_UInt16* ns) {
56685UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56686UA_VariableAttributes attr = UA_VariableAttributes_default;
56687attr.minimumSamplingInterval = 0.000000;
56688attr.userAccessLevel = 1;
56689attr.accessLevel = 1;
56690/* Value rank inherited */
56691attr.valueRank = -2;
56692attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56693UA_Int32 *variablenode_ns_0_i_113_variant_DataContents = UA_Int32_new();
56694if (!variablenode_ns_0_i_113_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56695UA_Int32_init(p: variablenode_ns_0_i_113_variant_DataContents);
56696*variablenode_ns_0_i_113_variant_DataContents = (UA_Int32) 2;
56697UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_113_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56698attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56699retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56700requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 113LU),
56701parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU),
56702referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56703browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56704typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56705attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56706UA_Int32_delete(p: variablenode_ns_0_i_113_variant_DataContents);
56707return retVal;
56708}
56709
56710static UA_StatusCode function_namespace0_generated_168_finish(UA_Server *server, UA_UInt16* ns) {
56711return UA_Server_addNode_finish(server,
56712nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 113LU)
56713);
56714}
56715
56716/* Mandatory - ns=0;i=78 */
56717
56718static UA_StatusCode function_namespace0_generated_169_begin(UA_Server *server, UA_UInt16* ns) {
56719UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56720UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56721attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Mandatory");
56722retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56723requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU),
56724parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56725referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56726browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Mandatory"),
56727typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56728attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56729retVal |= UA_Server_addReference(server, sourceId: UA_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);
56730retVal |= UA_Server_addReference(server, sourceId: UA_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);
56731retVal |= UA_Server_addReference(server, sourceId: UA_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);
56732retVal |= UA_Server_addReference(server, sourceId: UA_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);
56733retVal |= UA_Server_addReference(server, sourceId: UA_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);
56734retVal |= UA_Server_addReference(server, sourceId: UA_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);
56735retVal |= UA_Server_addReference(server, sourceId: UA_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);
56736retVal |= UA_Server_addReference(server, sourceId: UA_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);
56737retVal |= UA_Server_addReference(server, sourceId: UA_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);
56738retVal |= UA_Server_addReference(server, sourceId: UA_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);
56739retVal |= UA_Server_addReference(server, sourceId: UA_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);
56740retVal |= UA_Server_addReference(server, sourceId: UA_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);
56741retVal |= UA_Server_addReference(server, sourceId: UA_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);
56742retVal |= UA_Server_addReference(server, sourceId: UA_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);
56743retVal |= UA_Server_addReference(server, sourceId: UA_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);
56744retVal |= UA_Server_addReference(server, sourceId: UA_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);
56745retVal |= UA_Server_addReference(server, sourceId: UA_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);
56746retVal |= UA_Server_addReference(server, sourceId: UA_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);
56747retVal |= UA_Server_addReference(server, sourceId: UA_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);
56748return retVal;
56749}
56750
56751static UA_StatusCode function_namespace0_generated_169_finish(UA_Server *server, UA_UInt16* ns) {
56752return UA_Server_addNode_finish(server,
56753nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU)
56754);
56755}
56756
56757/* NamingRule - ns=0;i=112 */
56758
56759static UA_StatusCode function_namespace0_generated_170_begin(UA_Server *server, UA_UInt16* ns) {
56760UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56761UA_VariableAttributes attr = UA_VariableAttributes_default;
56762attr.minimumSamplingInterval = 0.000000;
56763attr.userAccessLevel = 1;
56764attr.accessLevel = 1;
56765/* Value rank inherited */
56766attr.valueRank = -2;
56767attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56768UA_Int32 *variablenode_ns_0_i_112_variant_DataContents = UA_Int32_new();
56769if (!variablenode_ns_0_i_112_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56770UA_Int32_init(p: variablenode_ns_0_i_112_variant_DataContents);
56771*variablenode_ns_0_i_112_variant_DataContents = (UA_Int32) 1;
56772UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_112_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56773attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56774retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56775requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 112LU),
56776parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU),
56777referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56778browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56779typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56780attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56781UA_Int32_delete(p: variablenode_ns_0_i_112_variant_DataContents);
56782return retVal;
56783}
56784
56785static UA_StatusCode function_namespace0_generated_170_finish(UA_Server *server, UA_UInt16* ns) {
56786return UA_Server_addNode_finish(server,
56787nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 112LU)
56788);
56789}
56790
56791/* MandatoryPlaceholder - ns=0;i=11510 */
56792
56793static UA_StatusCode function_namespace0_generated_171_begin(UA_Server *server, UA_UInt16* ns) {
56794UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56795UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56796attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MandatoryPlaceholder");
56797retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56798requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU),
56799parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56800referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56801browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MandatoryPlaceholder"),
56802typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56803attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56804return retVal;
56805}
56806
56807static UA_StatusCode function_namespace0_generated_171_finish(UA_Server *server, UA_UInt16* ns) {
56808return UA_Server_addNode_finish(server,
56809nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU)
56810);
56811}
56812
56813/* NamingRule - ns=0;i=11511 */
56814
56815static UA_StatusCode function_namespace0_generated_172_begin(UA_Server *server, UA_UInt16* ns) {
56816UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56817UA_VariableAttributes attr = UA_VariableAttributes_default;
56818attr.minimumSamplingInterval = 0.000000;
56819attr.userAccessLevel = 1;
56820attr.accessLevel = 1;
56821/* Value rank inherited */
56822attr.valueRank = -2;
56823attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56824UA_Int32 *variablenode_ns_0_i_11511_variant_DataContents = UA_Int32_new();
56825if (!variablenode_ns_0_i_11511_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56826UA_Int32_init(p: variablenode_ns_0_i_11511_variant_DataContents);
56827*variablenode_ns_0_i_11511_variant_DataContents = (UA_Int32) 1;
56828UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_11511_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56829attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56830retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56831requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11511LU),
56832parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU),
56833referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56834browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56835typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56836attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56837UA_Int32_delete(p: variablenode_ns_0_i_11511_variant_DataContents);
56838return retVal;
56839}
56840
56841static UA_StatusCode function_namespace0_generated_172_finish(UA_Server *server, UA_UInt16* ns) {
56842return UA_Server_addNode_finish(server,
56843nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11511LU)
56844);
56845}
56846
56847/* OptionalPlaceholder - ns=0;i=11508 */
56848
56849static UA_StatusCode function_namespace0_generated_173_begin(UA_Server *server, UA_UInt16* ns) {
56850UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56851UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56852attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OptionalPlaceholder");
56853retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56854requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU),
56855parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56856referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56857browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OptionalPlaceholder"),
56858typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56859attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56860return retVal;
56861}
56862
56863static UA_StatusCode function_namespace0_generated_173_finish(UA_Server *server, UA_UInt16* ns) {
56864return UA_Server_addNode_finish(server,
56865nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU)
56866);
56867}
56868
56869/* NamingRule - ns=0;i=11509 */
56870
56871static UA_StatusCode function_namespace0_generated_174_begin(UA_Server *server, UA_UInt16* ns) {
56872UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56873UA_VariableAttributes attr = UA_VariableAttributes_default;
56874attr.minimumSamplingInterval = 0.000000;
56875attr.userAccessLevel = 1;
56876attr.accessLevel = 1;
56877/* Value rank inherited */
56878attr.valueRank = -2;
56879attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56880UA_Int32 *variablenode_ns_0_i_11509_variant_DataContents = UA_Int32_new();
56881if (!variablenode_ns_0_i_11509_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56882UA_Int32_init(p: variablenode_ns_0_i_11509_variant_DataContents);
56883*variablenode_ns_0_i_11509_variant_DataContents = (UA_Int32) 2;
56884UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_11509_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56885attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56886retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56887requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11509LU),
56888parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU),
56889referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56890browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56891typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56892attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56893UA_Int32_delete(p: variablenode_ns_0_i_11509_variant_DataContents);
56894return retVal;
56895}
56896
56897static UA_StatusCode function_namespace0_generated_174_finish(UA_Server *server, UA_UInt16* ns) {
56898return UA_Server_addNode_finish(server,
56899nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11509LU)
56900);
56901}
56902
56903/* NamingRule - ns=0;i=111 */
56904
56905static UA_StatusCode function_namespace0_generated_175_begin(UA_Server *server, UA_UInt16* ns) {
56906UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56907UA_VariableAttributes attr = UA_VariableAttributes_default;
56908attr.minimumSamplingInterval = 0.000000;
56909attr.userAccessLevel = 1;
56910attr.accessLevel = 1;
56911/* Value rank inherited */
56912attr.valueRank = -2;
56913attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56914UA_Int32 *variablenode_ns_0_i_111_variant_DataContents = UA_Int32_new();
56915if (!variablenode_ns_0_i_111_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56916UA_Int32_init(p: variablenode_ns_0_i_111_variant_DataContents);
56917*variablenode_ns_0_i_111_variant_DataContents = (UA_Int32) 1;
56918UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_111_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56919attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56920retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56921requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 111LU),
56922parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56923referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56924browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56925typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56926attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56927UA_Int32_delete(p: variablenode_ns_0_i_111_variant_DataContents);
56928retVal |= 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);
56929return retVal;
56930}
56931
56932static UA_StatusCode function_namespace0_generated_175_finish(UA_Server *server, UA_UInt16* ns) {
56933return UA_Server_addNode_finish(server,
56934nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 111LU)
56935);
56936}
56937
56938/* DataTypeEncodingType - ns=0;i=76 */
56939
56940static UA_StatusCode function_namespace0_generated_176_begin(UA_Server *server, UA_UInt16* ns) {
56941UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56942UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
56943attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeEncodingType");
56944retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
56945requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
56946parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
56947referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
56948browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeEncodingType"),
56949 typeDefinition: UA_NODEID_NULL,
56950attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
56951return retVal;
56952}
56953
56954static UA_StatusCode function_namespace0_generated_176_finish(UA_Server *server, UA_UInt16* ns) {
56955return UA_Server_addNode_finish(server,
56956nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU)
56957);
56958}
56959
56960/* Default Binary - ns=0;i=8251 */
56961
56962static UA_StatusCode function_namespace0_generated_177_begin(UA_Server *server, UA_UInt16* ns) {
56963UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56964UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56965attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary");
56966retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56967requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8251LU),
56968parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56969referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56970browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"),
56971typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
56972attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56973retVal |= 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);
56974return retVal;
56975}
56976
56977static UA_StatusCode function_namespace0_generated_177_finish(UA_Server *server, UA_UInt16* ns) {
56978return UA_Server_addNode_finish(server,
56979nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8251LU)
56980);
56981}
56982
56983/* Default Binary - ns=0;i=298 */
56984
56985static UA_StatusCode function_namespace0_generated_178_begin(UA_Server *server, UA_UInt16* ns) {
56986UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56987UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56988attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary");
56989retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56990requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 298LU),
56991parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56992referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56993browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"),
56994typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
56995attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56996retVal |= 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);
56997return retVal;
56998}
56999
57000static UA_StatusCode function_namespace0_generated_178_finish(UA_Server *server, UA_UInt16* ns) {
57001return UA_Server_addNode_finish(server,
57002nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 298LU)
57003);
57004}
57005
57006/* Default JSON - ns=0;i=15376 */
57007
57008static UA_StatusCode function_namespace0_generated_179_begin(UA_Server *server, UA_UInt16* ns) {
57009UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57010UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57011attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default JSON");
57012retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57013requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15376LU),
57014parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57015referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57016browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default JSON"),
57017typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
57018attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57019retVal |= 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);
57020return retVal;
57021}
57022
57023static UA_StatusCode function_namespace0_generated_179_finish(UA_Server *server, UA_UInt16* ns) {
57024return UA_Server_addNode_finish(server,
57025nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15376LU)
57026);
57027}
57028
57029/* Default JSON - ns=0;i=15375 */
57030
57031static UA_StatusCode function_namespace0_generated_180_begin(UA_Server *server, UA_UInt16* ns) {
57032UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57033UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57034attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default JSON");
57035retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57036requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15375LU),
57037parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57038referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57039browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default JSON"),
57040typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
57041attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57042retVal |= 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);
57043return retVal;
57044}
57045
57046static UA_StatusCode function_namespace0_generated_180_finish(UA_Server *server, UA_UInt16* ns) {
57047return UA_Server_addNode_finish(server,
57048nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15375LU)
57049);
57050}
57051
57052/* DataTypeSystemType - ns=0;i=75 */
57053
57054static UA_StatusCode function_namespace0_generated_181_begin(UA_Server *server, UA_UInt16* ns) {
57055UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57056UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
57057attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeSystemType");
57058retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
57059requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU),
57060parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
57061referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
57062browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeSystemType"),
57063 typeDefinition: UA_NODEID_NULL,
57064attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
57065return retVal;
57066}
57067
57068static UA_StatusCode function_namespace0_generated_181_finish(UA_Server *server, UA_UInt16* ns) {
57069return UA_Server_addNode_finish(server,
57070nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU)
57071);
57072}
57073
57074/* OPC Binary - ns=0;i=93 */
57075
57076static UA_StatusCode function_namespace0_generated_182_begin(UA_Server *server, UA_UInt16* ns) {
57077UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57078UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57079attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OPC Binary");
57080retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57081requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU),
57082parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 90LU),
57083referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU),
57084browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OPC Binary"),
57085typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU),
57086attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57087return retVal;
57088}
57089
57090static UA_StatusCode function_namespace0_generated_182_finish(UA_Server *server, UA_UInt16* ns) {
57091return UA_Server_addNode_finish(server,
57092nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU)
57093);
57094}
57095
57096/* XML Schema - ns=0;i=92 */
57097
57098static UA_StatusCode function_namespace0_generated_183_begin(UA_Server *server, UA_UInt16* ns) {
57099UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57100UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57101attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "XML Schema");
57102retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57103requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 92LU),
57104parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 90LU),
57105referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU),
57106browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "XML Schema"),
57107typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU),
57108attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57109return retVal;
57110}
57111
57112static UA_StatusCode function_namespace0_generated_183_finish(UA_Server *server, UA_UInt16* ns) {
57113return UA_Server_addNode_finish(server,
57114nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 92LU)
57115);
57116}
57117
57118/* DataTypeDictionaryType - ns=0;i=72 */
57119
57120static UA_StatusCode function_namespace0_generated_184_begin(UA_Server *server, UA_UInt16* ns) {
57121UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57122UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
57123/* Value rank inherited */
57124attr.valueRank = -2;
57125attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU);
57126attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeDictionaryType");
57127retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
57128requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU),
57129parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
57130referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
57131browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeDictionaryType"),
57132typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57133attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
57134return retVal;
57135}
57136
57137static UA_StatusCode function_namespace0_generated_184_finish(UA_Server *server, UA_UInt16* ns) {
57138return UA_Server_addNode_finish(server,
57139nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU)
57140);
57141}
57142
57143/* Opc.Ua - ns=0;i=7617 */
57144static 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};
57145
57146
57147
57148static UA_StatusCode function_namespace0_generated_185_begin(UA_Server *server, UA_UInt16* ns) {
57149UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57150UA_VariableAttributes attr = UA_VariableAttributes_default;
57151attr.minimumSamplingInterval = 0.000000;
57152attr.userAccessLevel = 1;
57153attr.accessLevel = 1;
57154/* Value rank inherited */
57155attr.valueRank = -2;
57156attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU);
57157UA_ByteString *variablenode_ns_0_i_7617_variant_DataContents = UA_ByteString_new();
57158if (!variablenode_ns_0_i_7617_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
57159UA_ByteString_init(p: variablenode_ns_0_i_7617_variant_DataContents);
57160variablenode_ns_0_i_7617_variant_DataContents->length = 177218;
57161variablenode_ns_0_i_7617_variant_DataContents->data = (UA_Byte *)(void*)(uintptr_t)variablenode_ns_0_i_7617_variant_DataContents_byteArray;
57162UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7617_variant_DataContents, type: &UA_TYPES[UA_TYPES_BYTESTRING]);
57163attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Opc.Ua");
57164retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57165requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU),
57166parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU),
57167referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
57168browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Opc.Ua"),
57169typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU),
57170attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57171variablenode_ns_0_i_7617_variant_DataContents->data = NULL;
57172variablenode_ns_0_i_7617_variant_DataContents->length = 0;
57173UA_ByteString_delete(p: variablenode_ns_0_i_7617_variant_DataContents);
57174return retVal;
57175}
57176
57177static UA_StatusCode function_namespace0_generated_185_finish(UA_Server *server, UA_UInt16* ns) {
57178return UA_Server_addNode_finish(server,
57179nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU)
57180);
57181}
57182
57183/* NamespaceUri - ns=0;i=107 */
57184
57185static UA_StatusCode function_namespace0_generated_186_begin(UA_Server *server, UA_UInt16* ns) {
57186UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57187UA_VariableAttributes attr = UA_VariableAttributes_default;
57188attr.minimumSamplingInterval = 0.000000;
57189attr.userAccessLevel = 1;
57190attr.accessLevel = 1;
57191/* Value rank inherited */
57192attr.valueRank = -2;
57193attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57194attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamespaceUri");
57195#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
57196attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A URI that uniquely identifies the dictionary.");
57197#endif
57198retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57199requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 107LU),
57200parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU),
57201referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57202browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamespaceUri"),
57203typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57204attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57205retVal |= 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);
57206return retVal;
57207}
57208
57209static UA_StatusCode function_namespace0_generated_186_finish(UA_Server *server, UA_UInt16* ns) {
57210return UA_Server_addNode_finish(server,
57211nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 107LU)
57212);
57213}
57214
57215/* DataTypeVersion - ns=0;i=106 */
57216
57217static UA_StatusCode function_namespace0_generated_187_begin(UA_Server *server, UA_UInt16* ns) {
57218UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57219UA_VariableAttributes attr = UA_VariableAttributes_default;
57220attr.minimumSamplingInterval = 0.000000;
57221attr.userAccessLevel = 1;
57222attr.accessLevel = 1;
57223/* Value rank inherited */
57224attr.valueRank = -2;
57225attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57226attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeVersion");
57227retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57228requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 106LU),
57229parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU),
57230referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57231browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeVersion"),
57232typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57233attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57234retVal |= 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);
57235return retVal;
57236}
57237
57238static UA_StatusCode function_namespace0_generated_187_finish(UA_Server *server, UA_UInt16* ns) {
57239return UA_Server_addNode_finish(server,
57240nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 106LU)
57241);
57242}
57243
57244/* DataTypeDescriptionType - ns=0;i=69 */
57245
57246static UA_StatusCode function_namespace0_generated_188_begin(UA_Server *server, UA_UInt16* ns) {
57247UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57248UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
57249/* Value rank inherited */
57250attr.valueRank = -2;
57251attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57252attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeDescriptionType");
57253retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
57254requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57255parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
57256referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
57257browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeDescriptionType"),
57258typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57259attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
57260return retVal;
57261}
57262
57263static UA_StatusCode function_namespace0_generated_188_finish(UA_Server *server, UA_UInt16* ns) {
57264return UA_Server_addNode_finish(server,
57265nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU)
57266);
57267}
57268
57269/* EnumValueType - ns=0;i=7656 */
57270
57271static UA_StatusCode function_namespace0_generated_189_begin(UA_Server *server, UA_UInt16* ns) {
57272UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57273UA_VariableAttributes attr = UA_VariableAttributes_default;
57274attr.minimumSamplingInterval = 0.000000;
57275attr.userAccessLevel = 1;
57276attr.accessLevel = 1;
57277/* Value rank inherited */
57278attr.valueRank = -2;
57279attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57280UA_String *variablenode_ns_0_i_7656_variant_DataContents = UA_String_new();
57281if (!variablenode_ns_0_i_7656_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
57282UA_String_init(p: variablenode_ns_0_i_7656_variant_DataContents);
57283*variablenode_ns_0_i_7656_variant_DataContents = UA_STRING_ALLOC("EnumValueType");
57284UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7656_variant_DataContents, type: &UA_TYPES[UA_TYPES_STRING]);
57285attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValueType");
57286retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57287requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7656LU),
57288parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU),
57289referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
57290browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValueType"),
57291typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57292attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57293UA_String_delete(p: variablenode_ns_0_i_7656_variant_DataContents);
57294retVal |= 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);
57295return retVal;
57296}
57297
57298static UA_StatusCode function_namespace0_generated_189_finish(UA_Server *server, UA_UInt16* ns) {
57299return UA_Server_addNode_finish(server,
57300nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7656LU)
57301);
57302}
57303
57304/* Argument - ns=0;i=7650 */
57305
57306static UA_StatusCode function_namespace0_generated_190_begin(UA_Server *server, UA_UInt16* ns) {
57307UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57308UA_VariableAttributes attr = UA_VariableAttributes_default;
57309attr.minimumSamplingInterval = 0.000000;
57310attr.userAccessLevel = 1;
57311attr.accessLevel = 1;
57312/* Value rank inherited */
57313attr.valueRank = -2;
57314attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57315UA_String *variablenode_ns_0_i_7650_variant_DataContents = UA_String_new();
57316if (!variablenode_ns_0_i_7650_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
57317UA_String_init(p: variablenode_ns_0_i_7650_variant_DataContents);
57318*variablenode_ns_0_i_7650_variant_DataContents = UA_STRING_ALLOC("Argument");
57319UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7650_variant_DataContents, type: &UA_TYPES[UA_TYPES_STRING]);
57320attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Argument");
57321retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57322requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7650LU),
57323parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU),
57324referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
57325browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Argument"),
57326typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57327attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57328UA_String_delete(p: variablenode_ns_0_i_7650_variant_DataContents);
57329retVal |= 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);
57330return retVal;
57331}
57332
57333static UA_StatusCode function_namespace0_generated_190_finish(UA_Server *server, UA_UInt16* ns) {
57334return UA_Server_addNode_finish(server,
57335nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7650LU)
57336);
57337}
57338
57339/* DictionaryFragment - ns=0;i=105 */
57340
57341static UA_StatusCode function_namespace0_generated_191_begin(UA_Server *server, UA_UInt16* ns) {
57342UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57343UA_VariableAttributes attr = UA_VariableAttributes_default;
57344attr.minimumSamplingInterval = 0.000000;
57345attr.userAccessLevel = 1;
57346attr.accessLevel = 1;
57347/* Value rank inherited */
57348attr.valueRank = -2;
57349attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU);
57350attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DictionaryFragment");
57351retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57352requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 105LU),
57353parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57354referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57355browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DictionaryFragment"),
57356typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57357attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57358retVal |= 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);
57359return retVal;
57360}
57361
57362static UA_StatusCode function_namespace0_generated_191_finish(UA_Server *server, UA_UInt16* ns) {
57363return UA_Server_addNode_finish(server,
57364nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 105LU)
57365);
57366}
57367
57368/* DataTypeVersion - ns=0;i=104 */
57369
57370static UA_StatusCode function_namespace0_generated_192_begin(UA_Server *server, UA_UInt16* ns) {
57371UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57372UA_VariableAttributes attr = UA_VariableAttributes_default;
57373attr.minimumSamplingInterval = 0.000000;
57374attr.userAccessLevel = 1;
57375attr.accessLevel = 1;
57376/* Value rank inherited */
57377attr.valueRank = -2;
57378attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57379attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeVersion");
57380retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57381requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 104LU),
57382parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57383referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57384browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeVersion"),
57385typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57386attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57387retVal |= 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);
57388return retVal;
57389}
57390
57391static UA_StatusCode function_namespace0_generated_192_finish(UA_Server *server, UA_UInt16* ns) {
57392return UA_Server_addNode_finish(server,
57393nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 104LU)
57394);
57395}
57396
57397/* Default XML - ns=0;i=3063 */
57398
57399static UA_StatusCode function_namespace0_generated_193_begin(UA_Server *server, UA_UInt16* ns) {
57400UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57401UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57402attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default XML");
57403retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57404requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3063LU),
57405parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57406referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57407browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default XML"),
57408typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
57409attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57410return retVal;
57411}
57412
57413static UA_StatusCode function_namespace0_generated_193_finish(UA_Server *server, UA_UInt16* ns) {
57414return UA_Server_addNode_finish(server,
57415nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3063LU)
57416);
57417}
57418
57419/* Default Binary - ns=0;i=3062 */
57420
57421static UA_StatusCode function_namespace0_generated_194_begin(UA_Server *server, UA_UInt16* ns) {
57422UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57423UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57424attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary");
57425retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57426requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3062LU),
57427parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57428referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57429browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"),
57430typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
57431attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57432return retVal;
57433}
57434
57435static UA_StatusCode function_namespace0_generated_194_finish(UA_Server *server, UA_UInt16* ns) {
57436return UA_Server_addNode_finish(server,
57437nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3062LU)
57438);
57439}
57440
57441UA_StatusCode namespace0_generated(UA_Server *server) {
57442UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57443/* Use namespace ids generated by the server */
57444UA_UInt16 ns[1];
57445ns[0] = UA_Server_addNamespace(server, name: "http://opcfoundation.org/UA/");
57446
57447/* Load custom datatype definitions into the server */
57448if((retVal = function_namespace0_generated_0_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57449if((retVal = function_namespace0_generated_0_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57450if((retVal = function_namespace0_generated_1_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57451if((retVal = function_namespace0_generated_1_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57452if((retVal = function_namespace0_generated_2_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57453if((retVal = function_namespace0_generated_2_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57454if((retVal = function_namespace0_generated_3_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57455if((retVal = function_namespace0_generated_3_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57456if((retVal = function_namespace0_generated_4_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57457if((retVal = function_namespace0_generated_4_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57458if((retVal = function_namespace0_generated_5_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57459if((retVal = function_namespace0_generated_5_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57460if((retVal = function_namespace0_generated_6_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57461if((retVal = function_namespace0_generated_7_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57462if((retVal = function_namespace0_generated_8_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57463if((retVal = function_namespace0_generated_9_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57464if((retVal = function_namespace0_generated_10_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57465if((retVal = function_namespace0_generated_11_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57466if((retVal = function_namespace0_generated_12_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57467if((retVal = function_namespace0_generated_13_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57468if((retVal = function_namespace0_generated_14_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57469if((retVal = function_namespace0_generated_15_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57470if((retVal = function_namespace0_generated_16_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57471if((retVal = function_namespace0_generated_17_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57472if((retVal = function_namespace0_generated_18_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57473if((retVal = function_namespace0_generated_19_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57474if((retVal = function_namespace0_generated_20_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57475if((retVal = function_namespace0_generated_21_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57476if((retVal = function_namespace0_generated_22_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57477if((retVal = function_namespace0_generated_23_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57478if((retVal = function_namespace0_generated_24_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57479if((retVal = function_namespace0_generated_25_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57480if((retVal = function_namespace0_generated_26_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57481if((retVal = function_namespace0_generated_27_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57482if((retVal = function_namespace0_generated_28_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57483if((retVal = function_namespace0_generated_29_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57484if((retVal = function_namespace0_generated_30_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57485if((retVal = function_namespace0_generated_31_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57486if((retVal = function_namespace0_generated_32_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57487if((retVal = function_namespace0_generated_33_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57488if((retVal = function_namespace0_generated_34_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57489if((retVal = function_namespace0_generated_35_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57490if((retVal = function_namespace0_generated_36_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57491if((retVal = function_namespace0_generated_37_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57492if((retVal = function_namespace0_generated_38_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57493if((retVal = function_namespace0_generated_39_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57494if((retVal = function_namespace0_generated_40_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57495if((retVal = function_namespace0_generated_41_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57496if((retVal = function_namespace0_generated_42_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57497if((retVal = function_namespace0_generated_43_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57498if((retVal = function_namespace0_generated_44_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57499if((retVal = function_namespace0_generated_45_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57500if((retVal = function_namespace0_generated_46_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57501if((retVal = function_namespace0_generated_47_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57502if((retVal = function_namespace0_generated_48_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57503if((retVal = function_namespace0_generated_49_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57504if((retVal = function_namespace0_generated_50_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57505if((retVal = function_namespace0_generated_51_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57506if((retVal = function_namespace0_generated_52_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57507if((retVal = function_namespace0_generated_53_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57508if((retVal = function_namespace0_generated_54_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57509if((retVal = function_namespace0_generated_55_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57510if((retVal = function_namespace0_generated_56_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57511if((retVal = function_namespace0_generated_57_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57512if((retVal = function_namespace0_generated_58_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57513if((retVal = function_namespace0_generated_59_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57514if((retVal = function_namespace0_generated_60_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57515if((retVal = function_namespace0_generated_61_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57516if((retVal = function_namespace0_generated_62_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57517if((retVal = function_namespace0_generated_63_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57518if((retVal = function_namespace0_generated_64_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57519if((retVal = function_namespace0_generated_65_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57520if((retVal = function_namespace0_generated_66_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57521if((retVal = function_namespace0_generated_67_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57522if((retVal = function_namespace0_generated_68_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57523if((retVal = function_namespace0_generated_69_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57524if((retVal = function_namespace0_generated_70_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57525if((retVal = function_namespace0_generated_71_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57526if((retVal = function_namespace0_generated_72_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57527if((retVal = function_namespace0_generated_73_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57528if((retVal = function_namespace0_generated_74_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57529if((retVal = function_namespace0_generated_75_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57530if((retVal = function_namespace0_generated_76_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57531if((retVal = function_namespace0_generated_77_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57532if((retVal = function_namespace0_generated_78_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57533if((retVal = function_namespace0_generated_79_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57534if((retVal = function_namespace0_generated_80_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57535if((retVal = function_namespace0_generated_81_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57536if((retVal = function_namespace0_generated_82_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57537if((retVal = function_namespace0_generated_83_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57538if((retVal = function_namespace0_generated_84_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57539if((retVal = function_namespace0_generated_85_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57540if((retVal = function_namespace0_generated_86_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57541if((retVal = function_namespace0_generated_87_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57542if((retVal = function_namespace0_generated_88_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57543if((retVal = function_namespace0_generated_89_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57544if((retVal = function_namespace0_generated_90_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57545if((retVal = function_namespace0_generated_91_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57546if((retVal = function_namespace0_generated_92_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57547if((retVal = function_namespace0_generated_93_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57548if((retVal = function_namespace0_generated_94_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57549if((retVal = function_namespace0_generated_95_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57550if((retVal = function_namespace0_generated_96_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57551if((retVal = function_namespace0_generated_97_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57552if((retVal = function_namespace0_generated_98_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57553if((retVal = function_namespace0_generated_99_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57554if((retVal = function_namespace0_generated_100_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57555if((retVal = function_namespace0_generated_101_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57556if((retVal = function_namespace0_generated_102_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57557if((retVal = function_namespace0_generated_103_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57558if((retVal = function_namespace0_generated_104_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57559if((retVal = function_namespace0_generated_105_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57560if((retVal = function_namespace0_generated_106_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57561if((retVal = function_namespace0_generated_107_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57562if((retVal = function_namespace0_generated_108_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57563if((retVal = function_namespace0_generated_109_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57564if((retVal = function_namespace0_generated_110_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57565if((retVal = function_namespace0_generated_111_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57566if((retVal = function_namespace0_generated_112_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57567if((retVal = function_namespace0_generated_113_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57568if((retVal = function_namespace0_generated_114_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57569if((retVal = function_namespace0_generated_115_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57570if((retVal = function_namespace0_generated_116_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57571if((retVal = function_namespace0_generated_117_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57572if((retVal = function_namespace0_generated_118_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57573if((retVal = function_namespace0_generated_119_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57574if((retVal = function_namespace0_generated_120_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57575if((retVal = function_namespace0_generated_121_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57576if((retVal = function_namespace0_generated_122_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57577if((retVal = function_namespace0_generated_123_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57578if((retVal = function_namespace0_generated_124_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57579if((retVal = function_namespace0_generated_125_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57580if((retVal = function_namespace0_generated_126_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57581if((retVal = function_namespace0_generated_127_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57582if((retVal = function_namespace0_generated_128_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57583if((retVal = function_namespace0_generated_129_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57584if((retVal = function_namespace0_generated_130_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57585if((retVal = function_namespace0_generated_131_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57586if((retVal = function_namespace0_generated_132_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57587if((retVal = function_namespace0_generated_133_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57588if((retVal = function_namespace0_generated_134_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57589if((retVal = function_namespace0_generated_135_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57590if((retVal = function_namespace0_generated_136_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57591if((retVal = function_namespace0_generated_137_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57592if((retVal = function_namespace0_generated_138_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57593if((retVal = function_namespace0_generated_139_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57594if((retVal = function_namespace0_generated_140_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57595if((retVal = function_namespace0_generated_141_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57596if((retVal = function_namespace0_generated_142_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57597if((retVal = function_namespace0_generated_143_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57598if((retVal = function_namespace0_generated_144_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57599if((retVal = function_namespace0_generated_145_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57600if((retVal = function_namespace0_generated_146_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57601if((retVal = function_namespace0_generated_147_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57602if((retVal = function_namespace0_generated_148_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57603if((retVal = function_namespace0_generated_149_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57604if((retVal = function_namespace0_generated_150_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57605if((retVal = function_namespace0_generated_151_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57606if((retVal = function_namespace0_generated_152_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57607if((retVal = function_namespace0_generated_153_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57608if((retVal = function_namespace0_generated_154_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57609if((retVal = function_namespace0_generated_155_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57610if((retVal = function_namespace0_generated_156_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57611if((retVal = function_namespace0_generated_157_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57612if((retVal = function_namespace0_generated_158_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57613if((retVal = function_namespace0_generated_159_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57614if((retVal = function_namespace0_generated_160_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57615if((retVal = function_namespace0_generated_161_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57616if((retVal = function_namespace0_generated_162_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57617if((retVal = function_namespace0_generated_163_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57618if((retVal = function_namespace0_generated_164_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57619if((retVal = function_namespace0_generated_165_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57620if((retVal = function_namespace0_generated_166_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57621if((retVal = function_namespace0_generated_167_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57622if((retVal = function_namespace0_generated_168_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57623if((retVal = function_namespace0_generated_169_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57624if((retVal = function_namespace0_generated_170_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57625if((retVal = function_namespace0_generated_171_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57626if((retVal = function_namespace0_generated_172_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57627if((retVal = function_namespace0_generated_173_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57628if((retVal = function_namespace0_generated_174_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57629if((retVal = function_namespace0_generated_175_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57630if((retVal = function_namespace0_generated_176_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57631if((retVal = function_namespace0_generated_177_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57632if((retVal = function_namespace0_generated_178_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57633if((retVal = function_namespace0_generated_179_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57634if((retVal = function_namespace0_generated_180_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57635if((retVal = function_namespace0_generated_181_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57636if((retVal = function_namespace0_generated_182_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57637if((retVal = function_namespace0_generated_183_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57638if((retVal = function_namespace0_generated_184_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57639if((retVal = function_namespace0_generated_185_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57640if((retVal = function_namespace0_generated_186_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57641if((retVal = function_namespace0_generated_187_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57642if((retVal = function_namespace0_generated_188_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57643if((retVal = function_namespace0_generated_189_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57644if((retVal = function_namespace0_generated_190_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57645if((retVal = function_namespace0_generated_191_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57646if((retVal = function_namespace0_generated_192_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57647if((retVal = function_namespace0_generated_193_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57648if((retVal = function_namespace0_generated_194_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57649if((retVal = function_namespace0_generated_194_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57650if((retVal = function_namespace0_generated_193_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57651if((retVal = function_namespace0_generated_192_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57652if((retVal = function_namespace0_generated_191_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57653if((retVal = function_namespace0_generated_190_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57654if((retVal = function_namespace0_generated_189_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57655if((retVal = function_namespace0_generated_188_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57656if((retVal = function_namespace0_generated_187_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57657if((retVal = function_namespace0_generated_186_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57658if((retVal = function_namespace0_generated_185_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57659if((retVal = function_namespace0_generated_184_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57660if((retVal = function_namespace0_generated_183_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57661if((retVal = function_namespace0_generated_182_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57662if((retVal = function_namespace0_generated_181_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57663if((retVal = function_namespace0_generated_180_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57664if((retVal = function_namespace0_generated_179_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57665if((retVal = function_namespace0_generated_178_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57666if((retVal = function_namespace0_generated_177_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57667if((retVal = function_namespace0_generated_176_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57668if((retVal = function_namespace0_generated_175_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57669if((retVal = function_namespace0_generated_174_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57670if((retVal = function_namespace0_generated_173_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57671if((retVal = function_namespace0_generated_172_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57672if((retVal = function_namespace0_generated_171_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57673if((retVal = function_namespace0_generated_170_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57674if((retVal = function_namespace0_generated_169_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57675if((retVal = function_namespace0_generated_168_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57676if((retVal = function_namespace0_generated_167_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57677if((retVal = function_namespace0_generated_166_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57678if((retVal = function_namespace0_generated_165_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57679if((retVal = function_namespace0_generated_164_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57680if((retVal = function_namespace0_generated_163_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57681if((retVal = function_namespace0_generated_162_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57682if((retVal = function_namespace0_generated_161_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57683if((retVal = function_namespace0_generated_160_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57684if((retVal = function_namespace0_generated_159_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57685if((retVal = function_namespace0_generated_158_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57686if((retVal = function_namespace0_generated_157_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57687if((retVal = function_namespace0_generated_156_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57688if((retVal = function_namespace0_generated_155_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57689if((retVal = function_namespace0_generated_154_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57690if((retVal = function_namespace0_generated_153_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57691if((retVal = function_namespace0_generated_152_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57692if((retVal = function_namespace0_generated_151_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57693if((retVal = function_namespace0_generated_150_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57694if((retVal = function_namespace0_generated_149_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57695if((retVal = function_namespace0_generated_148_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57696if((retVal = function_namespace0_generated_147_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57697if((retVal = function_namespace0_generated_146_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57698if((retVal = function_namespace0_generated_145_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57699if((retVal = function_namespace0_generated_144_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57700if((retVal = function_namespace0_generated_143_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57701if((retVal = function_namespace0_generated_142_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57702if((retVal = function_namespace0_generated_141_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57703if((retVal = function_namespace0_generated_140_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57704if((retVal = function_namespace0_generated_139_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57705if((retVal = function_namespace0_generated_138_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57706if((retVal = function_namespace0_generated_137_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57707if((retVal = function_namespace0_generated_136_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57708if((retVal = function_namespace0_generated_135_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57709if((retVal = function_namespace0_generated_134_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57710if((retVal = function_namespace0_generated_133_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57711if((retVal = function_namespace0_generated_132_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57712if((retVal = function_namespace0_generated_131_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57713if((retVal = function_namespace0_generated_130_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57714if((retVal = function_namespace0_generated_129_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57715if((retVal = function_namespace0_generated_128_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57716if((retVal = function_namespace0_generated_127_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57717if((retVal = function_namespace0_generated_126_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57718if((retVal = function_namespace0_generated_125_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57719if((retVal = function_namespace0_generated_124_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57720if((retVal = function_namespace0_generated_123_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57721if((retVal = function_namespace0_generated_122_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57722if((retVal = function_namespace0_generated_121_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57723if((retVal = function_namespace0_generated_120_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57724if((retVal = function_namespace0_generated_119_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57725if((retVal = function_namespace0_generated_118_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57726if((retVal = function_namespace0_generated_117_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57727if((retVal = function_namespace0_generated_116_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57728if((retVal = function_namespace0_generated_115_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57729if((retVal = function_namespace0_generated_114_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57730if((retVal = function_namespace0_generated_113_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57731if((retVal = function_namespace0_generated_112_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57732if((retVal = function_namespace0_generated_111_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57733if((retVal = function_namespace0_generated_110_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57734if((retVal = function_namespace0_generated_109_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57735if((retVal = function_namespace0_generated_108_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57736if((retVal = function_namespace0_generated_107_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57737if((retVal = function_namespace0_generated_106_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57738if((retVal = function_namespace0_generated_105_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57739if((retVal = function_namespace0_generated_104_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57740if((retVal = function_namespace0_generated_103_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57741if((retVal = function_namespace0_generated_102_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57742if((retVal = function_namespace0_generated_101_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57743if((retVal = function_namespace0_generated_100_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57744if((retVal = function_namespace0_generated_99_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57745if((retVal = function_namespace0_generated_98_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57746if((retVal = function_namespace0_generated_97_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57747if((retVal = function_namespace0_generated_96_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57748if((retVal = function_namespace0_generated_95_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57749if((retVal = function_namespace0_generated_94_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57750if((retVal = function_namespace0_generated_93_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57751if((retVal = function_namespace0_generated_92_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57752if((retVal = function_namespace0_generated_91_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57753if((retVal = function_namespace0_generated_90_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57754if((retVal = function_namespace0_generated_89_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57755if((retVal = function_namespace0_generated_88_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57756if((retVal = function_namespace0_generated_87_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57757if((retVal = function_namespace0_generated_86_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57758if((retVal = function_namespace0_generated_85_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57759if((retVal = function_namespace0_generated_84_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57760if((retVal = function_namespace0_generated_83_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57761if((retVal = function_namespace0_generated_82_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57762if((retVal = function_namespace0_generated_81_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57763if((retVal = function_namespace0_generated_80_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57764if((retVal = function_namespace0_generated_79_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57765if((retVal = function_namespace0_generated_78_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57766if((retVal = function_namespace0_generated_77_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57767if((retVal = function_namespace0_generated_76_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57768if((retVal = function_namespace0_generated_75_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57769if((retVal = function_namespace0_generated_74_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57770if((retVal = function_namespace0_generated_73_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57771if((retVal = function_namespace0_generated_72_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57772if((retVal = function_namespace0_generated_71_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57773if((retVal = function_namespace0_generated_70_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57774if((retVal = function_namespace0_generated_69_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57775if((retVal = function_namespace0_generated_68_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57776if((retVal = function_namespace0_generated_67_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57777if((retVal = function_namespace0_generated_66_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57778if((retVal = function_namespace0_generated_65_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57779if((retVal = function_namespace0_generated_64_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57780if((retVal = function_namespace0_generated_63_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57781if((retVal = function_namespace0_generated_62_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57782if((retVal = function_namespace0_generated_61_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57783if((retVal = function_namespace0_generated_60_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57784if((retVal = function_namespace0_generated_59_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57785if((retVal = function_namespace0_generated_58_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57786if((retVal = function_namespace0_generated_57_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57787if((retVal = function_namespace0_generated_56_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57788if((retVal = function_namespace0_generated_55_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57789if((retVal = function_namespace0_generated_54_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57790if((retVal = function_namespace0_generated_53_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57791if((retVal = function_namespace0_generated_52_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57792if((retVal = function_namespace0_generated_51_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57793if((retVal = function_namespace0_generated_50_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57794if((retVal = function_namespace0_generated_49_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57795if((retVal = function_namespace0_generated_48_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57796if((retVal = function_namespace0_generated_47_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57797if((retVal = function_namespace0_generated_46_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57798if((retVal = function_namespace0_generated_45_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57799if((retVal = function_namespace0_generated_44_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57800if((retVal = function_namespace0_generated_43_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57801if((retVal = function_namespace0_generated_42_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57802if((retVal = function_namespace0_generated_41_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57803if((retVal = function_namespace0_generated_40_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57804if((retVal = function_namespace0_generated_39_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57805if((retVal = function_namespace0_generated_38_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57806if((retVal = function_namespace0_generated_37_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57807if((retVal = function_namespace0_generated_36_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57808if((retVal = function_namespace0_generated_35_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57809if((retVal = function_namespace0_generated_34_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57810if((retVal = function_namespace0_generated_33_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57811if((retVal = function_namespace0_generated_32_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57812if((retVal = function_namespace0_generated_31_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57813if((retVal = function_namespace0_generated_30_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57814if((retVal = function_namespace0_generated_29_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57815if((retVal = function_namespace0_generated_28_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57816if((retVal = function_namespace0_generated_27_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57817if((retVal = function_namespace0_generated_26_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57818if((retVal = function_namespace0_generated_25_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57819if((retVal = function_namespace0_generated_24_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57820if((retVal = function_namespace0_generated_23_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57821if((retVal = function_namespace0_generated_22_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57822if((retVal = function_namespace0_generated_21_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57823if((retVal = function_namespace0_generated_20_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57824if((retVal = function_namespace0_generated_19_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57825if((retVal = function_namespace0_generated_18_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57826if((retVal = function_namespace0_generated_17_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57827if((retVal = function_namespace0_generated_16_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57828if((retVal = function_namespace0_generated_15_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57829if((retVal = function_namespace0_generated_14_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57830if((retVal = function_namespace0_generated_13_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57831if((retVal = function_namespace0_generated_12_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57832if((retVal = function_namespace0_generated_11_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57833if((retVal = function_namespace0_generated_10_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57834if((retVal = function_namespace0_generated_9_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57835if((retVal = function_namespace0_generated_8_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57836if((retVal = function_namespace0_generated_7_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57837if((retVal = function_namespace0_generated_6_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57838return retVal;
57839}
57840
57841/**** amalgamated original file "/src/ua_types_lex.c" ****/
57842
57843/* Generated by re2c 1.1.1 */
57844/* This Source Code Form is subject to the terms of the Mozilla Public
57845 * License, v. 2.0. If a copy of the MPL was not distributed with this
57846 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
57847 *
57848 * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
57849 *
57850 */
57851
57852
57853/* Lexing and parsing of builtin data types. These are helper functions that not
57854 * required by the SDK internally. But they are useful for users who want to use
57855 * standard-specified humand readable encodings for NodeIds, etc.
57856 *
57857 * This compilation unit uses the re2c lexer generator. The final C source is
57858 * generated with the following script:
57859 *
57860 * re2c -i --no-generation-date ua_types_lex.re > ua_types_lex.c
57861 *
57862 * In order that users of the SDK don't need to install re2c, always commit a
57863 * recent ua_types_lex.c if changes are made to the lexer. */
57864
57865#define YYCURSOR pos
57866#define YYMARKER context.marker
57867#define YYPEEK() (YYCURSOR < end) ? *YYCURSOR : 0 /* The lexer sees a stream of
57868 * \0 when the input ends*/
57869#define YYSKIP() ++YYCURSOR;
57870#define YYBACKUP() YYMARKER = YYCURSOR
57871#define YYRESTORE() YYCURSOR = YYMARKER
57872#define YYSTAGP(t) t = YYCURSOR
57873#define YYSTAGN(t) t = NULL
57874
57875typedef struct {
57876 const char *marker;
57877 const char *yyt1;const char *yyt2;const char *yyt3;const char *yyt4;const char *yyt5;
57878} LexContext;
57879
57880
57881
57882static UA_StatusCode
57883parse_guid(UA_Guid *guid, const UA_Byte *s, const UA_Byte *e) {
57884 size_t len = (size_t)(e - s);
57885 if(len != 36 || s[8] != '-' || s[13] != '-' || s[23] != '-')
57886 return UA_STATUSCODE_BADINTERNALERROR;
57887
57888 UA_UInt32 tmp;
57889 if(UA_readNumberWithBase(buf: s, buflen: 8, number: &tmp, base: 16) != 8)
57890 return UA_STATUSCODE_BADINTERNALERROR;
57891 guid->data1 = tmp;
57892
57893 if(UA_readNumberWithBase(buf: &s[9], buflen: 4, number: &tmp, base: 16) != 4)
57894 return UA_STATUSCODE_BADINTERNALERROR;
57895 guid->data2 = (UA_UInt16)tmp;
57896
57897 if(UA_readNumberWithBase(buf: &s[14], buflen: 4, number: &tmp, base: 16) != 4)
57898 return UA_STATUSCODE_BADINTERNALERROR;
57899 guid->data3 = (UA_UInt16)tmp;
57900
57901 if(UA_readNumberWithBase(buf: &s[19], buflen: 2, number: &tmp, base: 16) != 2)
57902 return UA_STATUSCODE_BADINTERNALERROR;
57903 guid->data4[0] = (UA_Byte)tmp;
57904
57905 if(UA_readNumberWithBase(buf: &s[21], buflen: 2, number: &tmp, base: 16) != 2)
57906 return UA_STATUSCODE_BADINTERNALERROR;
57907 guid->data4[1] = (UA_Byte)tmp;
57908
57909 for(size_t pos = 2, spos = 24; pos < 8; pos++, spos += 2) {
57910 if(UA_readNumberWithBase(buf: &s[spos], buflen: 2, number: &tmp, base: 16) != 2)
57911 return UA_STATUSCODE_BADINTERNALERROR;
57912 guid->data4[pos] = (UA_Byte)tmp;
57913 }
57914
57915 return UA_STATUSCODE_GOOD;
57916}
57917
57918UA_StatusCode
57919UA_Guid_parse(UA_Guid *guid, const UA_String str) {
57920 UA_StatusCode res = parse_guid(guid, s: str.data, e: str.data + str.length);
57921 if(res != UA_STATUSCODE_GOOD)
57922 *guid = UA_GUID_NULL;
57923 return res;
57924}
57925
57926static UA_StatusCode
57927parse_nodeid_body(UA_NodeId *id, const char *body, const char *end) {
57928 size_t len = (size_t)(end - (body+2));
57929 UA_StatusCode res = UA_STATUSCODE_GOOD;
57930 switch(*body) {
57931 case 'i': {
57932 if(UA_readNumber(buf: (const UA_Byte*)body+2, buflen: len, number: &id->identifier.numeric) != len)
57933 return UA_STATUSCODE_BADINTERNALERROR;
57934 id->identifierType = UA_NODEIDTYPE_NUMERIC;
57935 break;
57936 }
57937 case 's': {
57938 UA_String tmpstr;
57939 tmpstr.data = (UA_Byte*)(uintptr_t)body+2;
57940 tmpstr.length = len;
57941 res = UA_String_copy(src: &tmpstr, dst: &id->identifier.string);
57942 if(res != UA_STATUSCODE_GOOD)
57943 break;
57944 id->identifierType = UA_NODEIDTYPE_STRING;
57945 break;
57946 }
57947 case 'g':
57948 res = parse_guid(guid: &id->identifier.guid, s: (const UA_Byte*)body+2, e: (const UA_Byte*)end);
57949 if(res == UA_STATUSCODE_GOOD)
57950 id->identifierType = UA_NODEIDTYPE_GUID;
57951 break;
57952 case 'b':
57953 id->identifier.byteString.data =
57954 UA_unbase64(src: (const unsigned char*)body+2, len,
57955 out_len: &id->identifier.byteString.length);
57956 if(!id->identifier.byteString.data && len > 0)
57957 return UA_STATUSCODE_BADINTERNALERROR;
57958 id->identifierType = UA_NODEIDTYPE_BYTESTRING;
57959 break;
57960 default:
57961 return UA_STATUSCODE_BADINTERNALERROR;
57962 }
57963 return res;
57964}
57965
57966static UA_StatusCode
57967parse_nodeid(UA_NodeId *id, const char *pos, const char *end) {
57968 *id = UA_NODEID_NULL; /* Reset the NodeId */
57969 LexContext context;
57970 memset(s: &context, c: 0, n: sizeof(LexContext));
57971 const char *ns = NULL, *nse= NULL;
57972
57973
57974{
57975 char yych;
57976 yych = YYPEEK ();
57977 switch (yych) {
57978 case 'b':
57979 case 'g':
57980 case 'i':
57981 case 's':
57982 YYSTAGN (context.yyt1);
57983 YYSTAGN (context.yyt2);
57984 goto yy4;
57985 case 'n': goto yy5;
57986 default: goto yy2;
57987 }
57988yy2:
57989 YYSKIP ();
57990yy3:
57991 { (void)pos; return UA_STATUSCODE_BADINTERNALERROR; }
57992yy4:
57993 YYSKIP ();
57994 yych = YYPEEK ();
57995 switch (yych) {
57996 case '=': goto yy6;
57997 default: goto yy3;
57998 }
57999yy5:
58000 YYSKIP ();
58001 YYBACKUP ();
58002 yych = YYPEEK ();
58003 switch (yych) {
58004 case 's': goto yy8;
58005 default: goto yy3;
58006 }
58007yy6:
58008 YYSKIP ();
58009 ns = context.yyt1;
58010 nse = context.yyt2;
58011 {
58012 (void)pos; // Get rid of a dead store clang-analyzer warning
58013 if(ns) {
58014 UA_UInt32 tmp;
58015 size_t len = (size_t)(nse - ns);
58016 if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len)
58017 return UA_STATUSCODE_BADINTERNALERROR;
58018 id->namespaceIndex = (UA_UInt16)tmp;
58019 }
58020
58021 // From the current position until the end
58022 return parse_nodeid_body(id, body: &pos[-2], end);
58023 }
58024yy8:
58025 YYSKIP ();
58026 yych = YYPEEK ();
58027 switch (yych) {
58028 case '=': goto yy10;
58029 default: goto yy9;
58030 }
58031yy9:
58032 YYRESTORE ();
58033 goto yy3;
58034yy10:
58035 YYSKIP ();
58036 yych = YYPEEK ();
58037 switch (yych) {
58038 case '0':
58039 case '1':
58040 case '2':
58041 case '3':
58042 case '4':
58043 case '5':
58044 case '6':
58045 case '7':
58046 case '8':
58047 case '9':
58048 YYSTAGP (context.yyt1);
58049 goto yy11;
58050 default: goto yy9;
58051 }
58052yy11:
58053 YYSKIP ();
58054 yych = YYPEEK ();
58055 switch (yych) {
58056 case '0':
58057 case '1':
58058 case '2':
58059 case '3':
58060 case '4':
58061 case '5':
58062 case '6':
58063 case '7':
58064 case '8':
58065 case '9': goto yy11;
58066 case ';':
58067 YYSTAGP (context.yyt2);
58068 goto yy13;
58069 default: goto yy9;
58070 }
58071yy13:
58072 YYSKIP ();
58073 yych = YYPEEK ();
58074 switch (yych) {
58075 case 'b':
58076 case 'g':
58077 case 'i':
58078 case 's': goto yy14;
58079 default: goto yy9;
58080 }
58081yy14:
58082 YYSKIP ();
58083 yych = YYPEEK ();
58084 switch (yych) {
58085 case '=': goto yy6;
58086 default: goto yy9;
58087 }
58088}
58089
58090}
58091
58092UA_StatusCode
58093UA_NodeId_parse(UA_NodeId *id, const UA_String str) {
58094 UA_StatusCode res =
58095 parse_nodeid(id, pos: (const char*)str.data, end: (const char*)str.data+str.length);
58096 if(res != UA_STATUSCODE_GOOD)
58097 UA_NodeId_clear(p: id);
58098 return res;
58099}
58100
58101static UA_StatusCode
58102parse_expandednodeid(UA_ExpandedNodeId *id, const char *pos, const char *end) {
58103 *id = UA_EXPANDEDNODEID_NULL; /* Reset the NodeId */
58104 LexContext context;
58105 memset(s: &context, c: 0, n: sizeof(LexContext));
58106 const char *svr = NULL, *svre = NULL, *nsu = NULL, *ns = NULL, *body = NULL;
58107
58108
58109{
58110 char yych;
58111 yych = YYPEEK ();
58112 switch (yych) {
58113 case 'b':
58114 case 'g':
58115 case 'i':
58116 YYSTAGN (context.yyt1);
58117 YYSTAGN (context.yyt2);
58118 YYSTAGN (context.yyt3);
58119 YYSTAGP (context.yyt4);
58120 YYSTAGN (context.yyt5);
58121 goto yy19;
58122 case 'n':
58123 YYSTAGN (context.yyt1);
58124 YYSTAGN (context.yyt2);
58125 goto yy20;
58126 case 's':
58127 YYSTAGN (context.yyt1);
58128 YYSTAGN (context.yyt2);
58129 YYSTAGN (context.yyt3);
58130 YYSTAGP (context.yyt4);
58131 YYSTAGN (context.yyt5);
58132 goto yy21;
58133 default: goto yy17;
58134 }
58135yy17:
58136 YYSKIP ();
58137yy18:
58138 { (void)pos; return UA_STATUSCODE_BADINTERNALERROR; }
58139yy19:
58140 YYSKIP ();
58141 yych = YYPEEK ();
58142 switch (yych) {
58143 case '=': goto yy22;
58144 default: goto yy18;
58145 }
58146yy20:
58147 YYSKIP ();
58148 YYBACKUP ();
58149 yych = YYPEEK ();
58150 switch (yych) {
58151 case 's': goto yy24;
58152 default: goto yy18;
58153 }
58154yy21:
58155 YYSKIP ();
58156 YYBACKUP ();
58157 yych = YYPEEK ();
58158 switch (yych) {
58159 case '=': goto yy22;
58160 case 'v': goto yy26;
58161 default: goto yy18;
58162 }
58163yy22:
58164 YYSKIP ();
58165 svr = context.yyt1;
58166 svre = context.yyt2;
58167 ns = context.yyt3;
58168 nsu = context.yyt5;
58169 body = context.yyt4;
58170 {
58171 (void)pos; // Get rid of a dead store clang-analyzer warning
58172 if(svr) {
58173 size_t len = (size_t)((svre) - svr);
58174 if(UA_readNumber(buf: (const UA_Byte*)svr, buflen: len, number: &id->serverIndex) != len)
58175 return UA_STATUSCODE_BADINTERNALERROR;
58176 }
58177
58178 if(nsu) {
58179 size_t len = (size_t)((body-1) - nsu);
58180 UA_String nsuri;
58181 nsuri.data = (UA_Byte*)(uintptr_t)nsu;
58182 nsuri.length = len;
58183 UA_StatusCode res = UA_String_copy(src: &nsuri, dst: &id->namespaceUri);
58184 if(res != UA_STATUSCODE_GOOD)
58185 return res;
58186 } else if(ns) {
58187 UA_UInt32 tmp;
58188 size_t len = (size_t)((body-1) - ns);
58189 if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len)
58190 return UA_STATUSCODE_BADINTERNALERROR;
58191 id->nodeId.namespaceIndex = (UA_UInt16)tmp;
58192 }
58193
58194 // From the current position until the end
58195 return parse_nodeid_body(id: &id->nodeId, body: &pos[-2], end);
58196 }
58197yy24:
58198 YYSKIP ();
58199 yych = YYPEEK ();
58200 switch (yych) {
58201 case '=': goto yy27;
58202 case 'u': goto yy28;
58203 default: goto yy25;
58204 }
58205yy25:
58206 YYRESTORE ();
58207 goto yy18;
58208yy26:
58209 YYSKIP ();
58210 yych = YYPEEK ();
58211 switch (yych) {
58212 case 'r': goto yy29;
58213 default: goto yy25;
58214 }
58215yy27:
58216 YYSKIP ();
58217 yych = YYPEEK ();
58218 switch (yych) {
58219 case '0':
58220 case '1':
58221 case '2':
58222 case '3':
58223 case '4':
58224 case '5':
58225 case '6':
58226 case '7':
58227 case '8':
58228 case '9':
58229 YYSTAGP (context.yyt3);
58230 goto yy30;
58231 default: goto yy25;
58232 }
58233yy28:
58234 YYSKIP ();
58235 yych = YYPEEK ();
58236 switch (yych) {
58237 case '=': goto yy32;
58238 default: goto yy25;
58239 }
58240yy29:
58241 YYSKIP ();
58242 yych = YYPEEK ();
58243 switch (yych) {
58244 case '=': goto yy33;
58245 default: goto yy25;
58246 }
58247yy30:
58248 YYSKIP ();
58249 yych = YYPEEK ();
58250 switch (yych) {
58251 case '0':
58252 case '1':
58253 case '2':
58254 case '3':
58255 case '4':
58256 case '5':
58257 case '6':
58258 case '7':
58259 case '8':
58260 case '9': goto yy30;
58261 case ';': goto yy34;
58262 default: goto yy25;
58263 }
58264yy32:
58265 YYSKIP ();
58266 yych = YYPEEK ();
58267 switch (yych) {
58268 case '\n': goto yy25;
58269 case ';':
58270 YYSTAGP (context.yyt5);
58271 goto yy37;
58272 default:
58273 YYSTAGP (context.yyt5);
58274 goto yy35;
58275 }
58276yy33:
58277 YYSKIP ();
58278 yych = YYPEEK ();
58279 switch (yych) {
58280 case '0':
58281 case '1':
58282 case '2':
58283 case '3':
58284 case '4':
58285 case '5':
58286 case '6':
58287 case '7':
58288 case '8':
58289 case '9':
58290 YYSTAGP (context.yyt1);
58291 goto yy38;
58292 default: goto yy25;
58293 }
58294yy34:
58295 YYSKIP ();
58296 yych = YYPEEK ();
58297 switch (yych) {
58298 case 'b':
58299 case 'g':
58300 case 'i':
58301 case 's':
58302 YYSTAGP (context.yyt4);
58303 YYSTAGN (context.yyt5);
58304 goto yy40;
58305 default: goto yy25;
58306 }
58307yy35:
58308 YYSKIP ();
58309 yych = YYPEEK ();
58310 switch (yych) {
58311 case '\n': goto yy25;
58312 case ';': goto yy37;
58313 default: goto yy35;
58314 }
58315yy37:
58316 YYSKIP ();
58317 yych = YYPEEK ();
58318 switch (yych) {
58319 case 'b':
58320 case 'g':
58321 case 'i':
58322 case 's':
58323 YYSTAGN (context.yyt3);
58324 YYSTAGP (context.yyt4);
58325 goto yy40;
58326 default: goto yy25;
58327 }
58328yy38:
58329 YYSKIP ();
58330 yych = YYPEEK ();
58331 switch (yych) {
58332 case '0':
58333 case '1':
58334 case '2':
58335 case '3':
58336 case '4':
58337 case '5':
58338 case '6':
58339 case '7':
58340 case '8':
58341 case '9': goto yy38;
58342 case ';':
58343 YYSTAGP (context.yyt2);
58344 goto yy41;
58345 default: goto yy25;
58346 }
58347yy40:
58348 YYSKIP ();
58349 yych = YYPEEK ();
58350 switch (yych) {
58351 case '=': goto yy22;
58352 default: goto yy25;
58353 }
58354yy41:
58355 YYSKIP ();
58356 yych = YYPEEK ();
58357 switch (yych) {
58358 case 'b':
58359 case 'g':
58360 case 'i':
58361 case 's':
58362 YYSTAGN (context.yyt3);
58363 YYSTAGP (context.yyt4);
58364 YYSTAGN (context.yyt5);
58365 goto yy40;
58366 case 'n': goto yy42;
58367 default: goto yy25;
58368 }
58369yy42:
58370 YYSKIP ();
58371 yych = YYPEEK ();
58372 switch (yych) {
58373 case 's': goto yy24;
58374 default: goto yy25;
58375 }
58376}
58377
58378}
58379
58380UA_StatusCode
58381UA_ExpandedNodeId_parse(UA_ExpandedNodeId *id, const UA_String str) {
58382 UA_StatusCode res =
58383 parse_expandednodeid(id, pos: (const char*)str.data, end: (const char*)str.data+str.length);
58384 if(res != UA_STATUSCODE_GOOD)
58385 UA_ExpandedNodeId_clear(p: id);
58386 return res;
58387}
58388
58389static UA_StatusCode
58390relativepath_addelem(UA_RelativePath *rp, UA_RelativePathElement *el) {
58391 /* Allocate memory */
58392 UA_RelativePathElement *newArray = (UA_RelativePathElement*)
58393 UA_realloc(ptr: rp->elements, size: sizeof(UA_RelativePathElement) * (rp->elementsSize + 1));
58394 if(!newArray)
58395 return UA_STATUSCODE_BADOUTOFMEMORY;
58396 rp->elements = newArray;
58397
58398 /* Move to the target */
58399 rp->elements[rp->elementsSize] = *el;
58400 rp->elementsSize++;
58401 return UA_STATUSCODE_GOOD;
58402}
58403
58404/* Parse name string with '&' as the escape character */
58405static UA_StatusCode
58406parse_refpath_qn_name(UA_QualifiedName *qn, const char **pos, const char *end) {
58407 /* Allocate the max length the name can have */
58408 size_t maxlen = (size_t)(end - *pos);
58409 if(maxlen == 0) {
58410 qn->name.data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL;
58411 return UA_STATUSCODE_GOOD;
58412 }
58413 char *name = (char*)UA_malloc(size: maxlen);
58414 if(!name)
58415 return UA_STATUSCODE_BADOUTOFMEMORY;
58416
58417 size_t index = 0;
58418 for(; *pos < end; (*pos)++) {
58419 char c = **pos;
58420 /* Unescaped special characer: The end of the QualifiedName */
58421 if(c == '/' || c == '.' || c == '<' || c == '>' ||
58422 c == ':' || c == '#' || c == '!')
58423 break;
58424
58425 /* Escaped character */
58426 if(c == '&') {
58427 (*pos)++;
58428 if(*pos >= end ||
58429 (**pos != '/' && **pos != '.' && **pos != '<' && **pos != '>' &&
58430 **pos != ':' && **pos != '#' && **pos != '!' && **pos != '&')) {
58431 UA_free(ptr: name);
58432 return UA_STATUSCODE_BADINTERNALERROR;
58433 }
58434 c = **pos;
58435 }
58436
58437 /* Unescaped normal character */
58438 name[index] = c;
58439 index++;
58440 }
58441
58442 if(index > 0) {
58443 qn->name.data = (UA_Byte*)name;
58444 qn->name.length = index;
58445 } else {
58446 qn->name.data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL;
58447 UA_free(ptr: name);
58448 }
58449 return UA_STATUSCODE_GOOD;
58450}
58451
58452static UA_StatusCode
58453parse_refpath_qn(UA_QualifiedName *qn, const char *pos, const char *end) {
58454 LexContext context;
58455 memset(s: &context, c: 0, n: sizeof(LexContext));
58456 const char *ns = NULL, *nse = NULL;
58457 UA_QualifiedName_init(p: qn);
58458
58459
58460{
58461 char yych;
58462 yych = YYPEEK ();
58463 switch (yych) {
58464 case '0':
58465 case '1':
58466 case '2':
58467 case '3':
58468 case '4':
58469 case '5':
58470 case '6':
58471 case '7':
58472 case '8':
58473 case '9':
58474 YYSTAGP (context.yyt1);
58475 goto yy47;
58476 default: goto yy45;
58477 }
58478yy45:
58479 YYSKIP ();
58480yy46:
58481 { pos--; goto parse_qn_name; }
58482yy47:
58483 YYSKIP ();
58484 YYBACKUP ();
58485 yych = YYPEEK ();
58486 switch (yych) {
58487 case '0':
58488 case '1':
58489 case '2':
58490 case '3':
58491 case '4':
58492 case '5':
58493 case '6':
58494 case '7':
58495 case '8':
58496 case '9':
58497 case ':': goto yy49;
58498 default: goto yy46;
58499 }
58500yy48:
58501 YYSKIP ();
58502 yych = YYPEEK ();
58503yy49:
58504 switch (yych) {
58505 case '0':
58506 case '1':
58507 case '2':
58508 case '3':
58509 case '4':
58510 case '5':
58511 case '6':
58512 case '7':
58513 case '8':
58514 case '9': goto yy48;
58515 case ':':
58516 YYSTAGP (context.yyt2);
58517 goto yy51;
58518 default: goto yy50;
58519 }
58520yy50:
58521 YYRESTORE ();
58522 goto yy46;
58523yy51:
58524 YYSKIP ();
58525 ns = context.yyt1;
58526 nse = context.yyt2;
58527 {
58528 UA_UInt32 tmp;
58529 size_t len = (size_t)(nse - ns);
58530 if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len)
58531 return UA_STATUSCODE_BADINTERNALERROR;
58532 qn->namespaceIndex = (UA_UInt16)tmp;
58533 goto parse_qn_name;
58534 }
58535}
58536
58537
58538 parse_qn_name:
58539 return parse_refpath_qn_name(qn, pos: &pos, end);
58540}
58541
58542/* List of well-known ReferenceTypes that don't require lookup in the server */
58543
58544typedef struct {
58545 char *browseName;
58546 UA_UInt32 identifier;
58547} RefTypeNames;
58548
58549#define KNOWNREFTYPES 17
58550static const RefTypeNames knownRefTypes[KNOWNREFTYPES] = {
58551 {"References", UA_NS0ID_REFERENCES},
58552 {"HierachicalReferences", UA_NS0ID_HIERARCHICALREFERENCES},
58553 {"NonHierachicalReferences", UA_NS0ID_NONHIERARCHICALREFERENCES},
58554 {"HasChild", UA_NS0ID_HASCHILD},
58555 {"Aggregates", UA_NS0ID_AGGREGATES},
58556 {"HasComponent", UA_NS0ID_HASCOMPONENT},
58557 {"HasProperty", UA_NS0ID_HASPROPERTY},
58558 {"HasOrderedComponent", UA_NS0ID_HASORDEREDCOMPONENT},
58559 {"HasSubtype", UA_NS0ID_HASSUBTYPE},
58560 {"Organizes", UA_NS0ID_ORGANIZES},
58561 {"HasModellingRule", UA_NS0ID_HASMODELLINGRULE},
58562 {"HasTypeDefinition", UA_NS0ID_HASTYPEDEFINITION},
58563 {"HasEncoding", UA_NS0ID_HASENCODING},
58564 {"GeneratesEvent", UA_NS0ID_GENERATESEVENT},
58565 {"AlwaysGeneratesEvent", UA_NS0ID_ALWAYSGENERATESEVENT},
58566 {"HasEventSource", UA_NS0ID_HASEVENTSOURCE},
58567 {"HasNotifier", UA_NS0ID_HASNOTIFIER}
58568};
58569
58570static UA_StatusCode
58571lookup_reftype(UA_NodeId *refTypeId, UA_QualifiedName *qn) {
58572 if(qn->namespaceIndex != 0)
58573 return UA_STATUSCODE_BADNOTFOUND;
58574
58575 for(size_t i = 0; i < KNOWNREFTYPES; i++) {
58576 UA_String tmp = UA_STRING(chars: knownRefTypes[i].browseName);
58577 if(UA_String_equal(s1: &qn->name, s2: &tmp)) {
58578 *refTypeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: knownRefTypes[i].identifier);
58579 return UA_STATUSCODE_GOOD;
58580 }
58581 }
58582
58583 return UA_STATUSCODE_BADNOTFOUND;
58584}
58585
58586static UA_StatusCode
58587parse_relativepath(UA_RelativePath *rp, const char *pos, const char *end) {
58588 LexContext context;
58589 memset(s: &context, c: 0, n: sizeof(LexContext));
58590 const char *begin = NULL, *finish = NULL;
58591 UA_StatusCode res = UA_STATUSCODE_GOOD;
58592 UA_RelativePath_init(p: rp); /* Reset the BrowsePath */
58593
58594 /* Add one element to the path in every iteration */
58595 UA_RelativePathElement current;
58596 loop:
58597 UA_RelativePathElement_init(p: &current);
58598 current.includeSubtypes = true; /* Follow subtypes by default */
58599
58600 /* Get the ReferenceType and its modifiers */
58601
58602{
58603 char yych;
58604 unsigned int yyaccept = 0;
58605 yych = YYPEEK ();
58606 switch (yych) {
58607 case 0x00: goto yy55;
58608 case '.': goto yy59;
58609 case '/': goto yy61;
58610 case '<': goto yy63;
58611 default: goto yy57;
58612 }
58613yy55:
58614 YYSKIP ();
58615 { (void)pos; return UA_STATUSCODE_GOOD; }
58616yy57:
58617 YYSKIP ();
58618yy58:
58619 { (void)pos; return UA_STATUSCODE_BADINTERNALERROR; }
58620yy59:
58621 YYSKIP ();
58622 {
58623 current.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES);
58624 goto reftype_target;
58625 }
58626yy61:
58627 YYSKIP ();
58628 {
58629 current.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
58630 goto reftype_target;
58631 }
58632yy63:
58633 yyaccept = 0;
58634 YYSKIP ();
58635 YYBACKUP ();
58636 yych = YYPEEK ();
58637 switch (yych) {
58638 case 0x00:
58639 case '>': goto yy58;
58640 case '&':
58641 YYSTAGP (context.yyt1);
58642 goto yy67;
58643 default:
58644 YYSTAGP (context.yyt1);
58645 goto yy64;
58646 }
58647yy64:
58648 YYSKIP ();
58649 yych = YYPEEK ();
58650 switch (yych) {
58651 case 0x00: goto yy66;
58652 case '&': goto yy67;
58653 case '>':
58654 YYSTAGP (context.yyt2);
58655 goto yy69;
58656 default: goto yy64;
58657 }
58658yy66:
58659 YYRESTORE ();
58660 if (yyaccept == 0) {
58661 goto yy58;
58662 } else {
58663 goto yy70;
58664 }
58665yy67:
58666 YYSKIP ();
58667 yych = YYPEEK ();
58668 switch (yych) {
58669 case 0x00: goto yy66;
58670 case '&': goto yy67;
58671 case '>':
58672 YYSTAGP (context.yyt2);
58673 goto yy71;
58674 default: goto yy64;
58675 }
58676yy69:
58677 YYSKIP ();
58678yy70:
58679 begin = context.yyt1;
58680 finish = context.yyt2;
58681 {
58682 for(; begin < finish; begin++) {
58683 if(*begin== '#')
58684 current.includeSubtypes = false;
58685 else if(*begin == '!')
58686 current.isInverse = true;
58687 else
58688 break;
58689 }
58690 UA_QualifiedName refqn;
58691 res |= parse_refpath_qn(qn: &refqn, pos: begin, end: finish);
58692 res |= lookup_reftype(refTypeId: &current.referenceTypeId, qn: &refqn);
58693 UA_QualifiedName_clear(p: &refqn);
58694 goto reftype_target;
58695 }
58696yy71:
58697 yyaccept = 1;
58698 YYSKIP ();
58699 YYBACKUP ();
58700 yych = YYPEEK ();
58701 switch (yych) {
58702 case 0x00: goto yy70;
58703 case '&': goto yy67;
58704 case '>':
58705 YYSTAGP (context.yyt2);
58706 goto yy69;
58707 default: goto yy64;
58708 }
58709}
58710
58711
58712 /* Get the TargetName component */
58713 reftype_target:
58714 if(res != UA_STATUSCODE_GOOD)
58715 return res;
58716
58717
58718{
58719 char yych;
58720 yych = YYPEEK ();
58721 switch (yych) {
58722 case 0x00:
58723 case '.':
58724 case '/':
58725 case '<': goto yy74;
58726 case '&':
58727 YYSTAGP (context.yyt1);
58728 goto yy79;
58729 default:
58730 YYSTAGP (context.yyt1);
58731 goto yy76;
58732 }
58733yy74:
58734 YYSKIP ();
58735 { pos--; goto add_element; }
58736yy76:
58737 YYSKIP ();
58738 yych = YYPEEK ();
58739 switch (yych) {
58740 case 0x00:
58741 case '.':
58742 case '/':
58743 case '<': goto yy78;
58744 case '&': goto yy79;
58745 default: goto yy76;
58746 }
58747yy78:
58748 begin = context.yyt1;
58749 {
58750 res = parse_refpath_qn(qn: &current.targetName, pos: begin, end: pos);
58751 goto add_element;
58752 }
58753yy79:
58754 YYSKIP ();
58755 yych = YYPEEK ();
58756 switch (yych) {
58757 case 0x00: goto yy78;
58758 case '&': goto yy79;
58759 default: goto yy76;
58760 }
58761}
58762
58763
58764 /* Add the current element to the path and continue to the next element */
58765 add_element:
58766 res |= relativepath_addelem(rp, el: &current);
58767 if(res != UA_STATUSCODE_GOOD) {
58768 UA_RelativePathElement_clear(p: &current);
58769 return res;
58770 }
58771 goto loop;
58772}
58773
58774UA_StatusCode
58775UA_RelativePath_parse(UA_RelativePath *rp, const UA_String str) {
58776 UA_StatusCode res =
58777 parse_relativepath(rp, pos: (const char*)str.data, end: (const char*)str.data+str.length);
58778 if(res != UA_STATUSCODE_GOOD)
58779 UA_RelativePath_clear(p: rp);
58780 return res;
58781}
58782
58783/**** amalgamated original file "/src/server/ua_subscription.c" ****/
58784
58785/* This Source Code Form is subject to the terms of the Mozilla Public
58786 * License, v. 2.0. If a copy of the MPL was not distributed with this
58787 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
58788 *
58789 * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
58790 * Copyright 2015 (c) Chris Iatrou
58791 * Copyright 2015-2016 (c) Sten Grüner
58792 * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
58793 * Copyright 2015 (c) Joakim L. Gilje
58794 * Copyright 2016-2017 (c) Florian Palm
58795 * Copyright 2015-2016 (c) Oleksiy Vasylyev
58796 * Copyright 2017 (c) frax2222
58797 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
58798 * Copyright 2017 (c) Ari Breitkreuz, fortiss GmbH
58799 * Copyright 2017 (c) Mattias Bornhager
58800 * Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
58801 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
58802 */
58803
58804
58805#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
58806
58807#define UA_MAX_RETRANSMISSIONQUEUESIZE 256
58808
58809UA_Subscription *
58810UA_Subscription_new(void) {
58811 /* Allocate the memory */
58812 UA_Subscription *newSub = (UA_Subscription*)UA_calloc(nmemb: 1, size: sizeof(UA_Subscription));
58813 if(!newSub)
58814 return NULL;
58815
58816 /* The first publish response is sent immediately */
58817 newSub->state = UA_SUBSCRIPTIONSTATE_NORMAL;
58818
58819 /* Even if the first publish response is a keepalive the sequence number is 1.
58820 * This can happen by a subscription without a monitored item (see CTT test scripts). */
58821 newSub->nextSequenceNumber = 1;
58822
58823 TAILQ_INIT(&newSub->retransmissionQueue);
58824 TAILQ_INIT(&newSub->notificationQueue);
58825 return newSub;
58826}
58827
58828void
58829UA_Subscription_delete(UA_Server *server, UA_Subscription *sub) {
58830 UA_LOCK_ASSERT(&server->serviceMutex, 1);
58831
58832 /* Unregister the publish callback */
58833 Subscription_unregisterPublishCallback(server, sub);
58834
58835 /* Remove the diagnostics object for the subscription */
58836#ifdef UA_ENABLE_DIAGNOSTICS
58837 if(sub->session) {
58838 /* Use a browse path to find the node */
58839 char subIdStr[32];
58840 snprintf(subIdStr, 32, "%u", sub->subscriptionId);
58841 UA_BrowsePath bp;
58842 UA_BrowsePath_init(&bp);
58843 bp.startingNode = sub->session->sessionId;
58844 UA_RelativePathElement rpe[2];
58845 memset(rpe, 0, sizeof(UA_RelativePathElement) * 2);
58846 rpe[0].targetName = UA_QUALIFIEDNAME(0, "SubscriptionDiagnosticsArray");
58847 rpe[1].targetName = UA_QUALIFIEDNAME(0, subIdStr);
58848 bp.relativePath.elements = rpe;
58849 bp.relativePath.elementsSize = 2;
58850 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, &bp);
58851
58852 /* Delete all nodes matching the browse path */
58853 for(size_t i = 0; i < bpr.targetsSize; i++) {
58854 if(bpr.targets[i].remainingPathIndex < UA_UINT32_MAX)
58855 continue;
58856 deleteNode(server, bpr.targets[i].targetId.nodeId, true);
58857 }
58858 UA_BrowsePathResult_clear(&bpr);
58859 }
58860#endif
58861
58862 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub, "Subscription deleted");
58863
58864 /* Detach from the session if necessary */
58865 if(sub->session)
58866 UA_Session_detachSubscription(server, session: sub->session, sub, true);
58867
58868 /* Remove from the server if not previously registered */
58869 if(sub->serverListEntry.le_prev) {
58870 LIST_REMOVE(sub, serverListEntry);
58871 UA_assert(server->subscriptionsSize > 0);
58872 server->subscriptionsSize--;
58873 server->serverDiagnosticsSummary.currentSubscriptionCount--;
58874 }
58875
58876 /* Delete monitored Items */
58877 UA_assert(server->monitoredItemsSize >= sub->monitoredItemsSize);
58878 UA_MonitoredItem *mon, *tmp_mon;
58879 LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, tmp_mon) {
58880 UA_MonitoredItem_delete(server, monitoredItem: mon);
58881 }
58882 UA_assert(sub->monitoredItemsSize == 0);
58883
58884 /* Delete Retransmission Queue */
58885 UA_NotificationMessageEntry *nme, *nme_tmp;
58886 TAILQ_FOREACH_SAFE(nme, &sub->retransmissionQueue, listEntry, nme_tmp) {
58887 TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry);
58888 UA_NotificationMessage_clear(p: &nme->message);
58889 UA_free(ptr: nme);
58890 if(sub->session)
58891 --sub->session->totalRetransmissionQueueSize;
58892 --sub->retransmissionQueueSize;
58893 }
58894 UA_assert(sub->retransmissionQueueSize == 0);
58895
58896 /* Add a delayed callback to remove the Subscription when the current jobs
58897 * have completed. Pointers to the subscription may still exist upwards in
58898 * the call stack. */
58899 sub->delayedFreePointers.callback = NULL;
58900 sub->delayedFreePointers.application = server;
58901 sub->delayedFreePointers.data = NULL;
58902 sub->delayedFreePointers.nextTime = UA_DateTime_nowMonotonic() + 1;
58903 sub->delayedFreePointers.interval = 0; /* Remove the structure */
58904 UA_Timer_addTimerEntry(t: &server->timer, te: &sub->delayedFreePointers, NULL);
58905}
58906
58907UA_MonitoredItem *
58908UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemId) {
58909 UA_MonitoredItem *mon;
58910 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
58911 if(mon->monitoredItemId == monitoredItemId)
58912 break;
58913 }
58914 return mon;
58915}
58916
58917static void
58918removeOldestRetransmissionMessageFromSub(UA_Subscription *sub) {
58919 UA_NotificationMessageEntry *oldestEntry =
58920 TAILQ_LAST(&sub->retransmissionQueue, NotificationMessageQueue);
58921 TAILQ_REMOVE(&sub->retransmissionQueue, oldestEntry, listEntry);
58922 UA_NotificationMessage_clear(p: &oldestEntry->message);
58923 UA_free(ptr: oldestEntry);
58924 --sub->retransmissionQueueSize;
58925 if(sub->session)
58926 --sub->session->totalRetransmissionQueueSize;
58927
58928#ifdef UA_ENABLE_DIAGNOSTICS
58929 sub->discardedMessageCount++;
58930#endif
58931}
58932
58933static void
58934removeOldestRetransmissionMessageFromSession(UA_Session *session) {
58935 UA_NotificationMessageEntry *oldestEntry = NULL;
58936 UA_Subscription *oldestSub = NULL;
58937 UA_Subscription *sub;
58938 TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
58939 UA_NotificationMessageEntry *first =
58940 TAILQ_LAST(&sub->retransmissionQueue, NotificationMessageQueue);
58941 if(!first)
58942 continue;
58943 if(!oldestEntry || oldestEntry->message.publishTime > first->message.publishTime) {
58944 oldestEntry = first;
58945 oldestSub = sub;
58946 }
58947 }
58948 UA_assert(oldestEntry);
58949 UA_assert(oldestSub);
58950
58951 removeOldestRetransmissionMessageFromSub(sub: oldestSub);
58952}
58953
58954static void
58955UA_Subscription_addRetransmissionMessage(UA_Server *server, UA_Subscription *sub,
58956 UA_NotificationMessageEntry *entry) {
58957 /* Release the oldest entry if there is not enough space */
58958 UA_Session *session = sub->session;
58959 if(sub->retransmissionQueueSize >= UA_MAX_RETRANSMISSIONQUEUESIZE) {
58960 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
58961 "Subscription retransmission queue overflow");
58962 removeOldestRetransmissionMessageFromSub(sub);
58963 } else if(session && server->config.maxRetransmissionQueueSize > 0 &&
58964 session->totalRetransmissionQueueSize >=
58965 server->config.maxRetransmissionQueueSize) {
58966 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
58967 "Session-wide retransmission queue overflow");
58968 removeOldestRetransmissionMessageFromSession(session: sub->session);
58969 }
58970
58971 /* Add entry */
58972 TAILQ_INSERT_TAIL(&sub->retransmissionQueue, entry, listEntry);
58973 ++sub->retransmissionQueueSize;
58974 if(session)
58975 ++session->totalRetransmissionQueueSize;
58976}
58977
58978UA_StatusCode
58979UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub, UA_UInt32 sequenceNumber) {
58980 /* Find the retransmission message */
58981 UA_NotificationMessageEntry *entry;
58982 TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
58983 if(entry->message.sequenceNumber == sequenceNumber)
58984 break;
58985 }
58986 if(!entry)
58987 return UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN;
58988
58989 /* Remove the retransmission message */
58990 TAILQ_REMOVE(&sub->retransmissionQueue, entry, listEntry);
58991 --sub->retransmissionQueueSize;
58992 UA_NotificationMessage_clear(p: &entry->message);
58993 UA_free(ptr: entry);
58994
58995 if(sub->session)
58996 --sub->session->totalRetransmissionQueueSize;
58997
58998 return UA_STATUSCODE_GOOD;
58999}
59000
59001/* The output counters are only set when the preparation is successful */
59002static UA_StatusCode
59003prepareNotificationMessage(UA_Server *server, UA_Subscription *sub,
59004 UA_NotificationMessage *message,
59005 size_t maxNotifications) {
59006 UA_assert(maxNotifications > 0);
59007
59008 /* Allocate an ExtensionObject for Event- and DataChange-Notifications. Also
59009 * there can be StatusChange-Notifications. The standard says in Part 4,
59010 * 7.2.1:
59011 *
59012 * If a Subscription contains MonitoredItems for events and data, this array
59013 * should have not more than 2 elements. */
59014 message->notificationData = (UA_ExtensionObject*)
59015 UA_Array_new(size: 2, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
59016 if(!message->notificationData)
59017 return UA_STATUSCODE_BADOUTOFMEMORY;
59018 message->notificationDataSize = 2;
59019
59020 /* Pre-allocate DataChangeNotifications */
59021 size_t notificationDataIdx = 0;
59022 size_t dcnPos = 0; /* How many DataChangeNotifications? */
59023 UA_DataChangeNotification *dcn = NULL;
59024 if(sub->dataChangeNotifications > 0) {
59025 dcn = UA_DataChangeNotification_new();
59026 if(!dcn) {
59027 UA_NotificationMessage_clear(p: message);
59028 return UA_STATUSCODE_BADOUTOFMEMORY;
59029 }
59030 UA_ExtensionObject_setValue(eo: message->notificationData, p: dcn,
59031 type: &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]);
59032 size_t dcnSize = sub->dataChangeNotifications;
59033 if(dcnSize > maxNotifications)
59034 dcnSize = maxNotifications;
59035 dcn->monitoredItems = (UA_MonitoredItemNotification*)
59036 UA_Array_new(size: dcnSize, type: &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
59037 if(!dcn->monitoredItems) {
59038 UA_NotificationMessage_clear(p: message);
59039 return UA_STATUSCODE_BADOUTOFMEMORY;
59040 }
59041 dcn->monitoredItemsSize = dcnSize;
59042 notificationDataIdx++;
59043 }
59044
59045#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59046 size_t enlPos = 0; /* How many EventNotifications? */
59047 UA_EventNotificationList *enl = NULL;
59048 if(sub->eventNotifications > 0) {
59049 enl = UA_EventNotificationList_new();
59050 if(!enl) {
59051 UA_NotificationMessage_clear(p: message);
59052 return UA_STATUSCODE_BADOUTOFMEMORY;
59053 }
59054 UA_ExtensionObject_setValue(eo: &message->notificationData[notificationDataIdx],
59055 p: enl, type: &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]);
59056 size_t enlSize = sub->eventNotifications;
59057 if(enlSize > maxNotifications)
59058 enlSize = maxNotifications;
59059 enl->events = (UA_EventFieldList*)
59060 UA_Array_new(size: enlSize, type: &UA_TYPES[UA_TYPES_EVENTFIELDLIST]);
59061 if(!enl->events) {
59062 UA_NotificationMessage_clear(p: message);
59063 return UA_STATUSCODE_BADOUTOFMEMORY;
59064 }
59065 enl->eventsSize = enlSize;
59066 notificationDataIdx++;
59067 }
59068#endif
59069
59070 UA_assert(notificationDataIdx > 0);
59071 message->notificationDataSize = notificationDataIdx;
59072
59073 /* <-- The point of no return --> */
59074
59075 /* How many notifications were moved to the response overall? */
59076 size_t totalNotifications = 0;
59077 UA_Notification *notification, *notification_tmp;
59078 TAILQ_FOREACH_SAFE(notification, &sub->notificationQueue,
59079 globalEntry, notification_tmp) {
59080 if(totalNotifications >= maxNotifications)
59081 break;
59082
59083 /* Move the content to the response */
59084 switch(notification->mon->itemToMonitor.attributeId) {
59085#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59086 case UA_ATTRIBUTEID_EVENTNOTIFIER:
59087 UA_assert(enl != NULL); /* Have at least one event notification */
59088 enl->events[enlPos] = notification->data.event;
59089 UA_EventFieldList_init(p: &notification->data.event);
59090 enlPos++;
59091 break;
59092#endif
59093 default:
59094 UA_assert(dcn != NULL); /* Have at least one change notification */
59095 dcn->monitoredItems[dcnPos] = notification->data.dataChange;
59096 UA_DataValue_init(p: &notification->data.dataChange.value);
59097 dcnPos++;
59098 break;
59099 }
59100
59101 /* If there are Notifications *before this one* in the MonitoredItem-
59102 * local queue, remove all of them. These are earlier Notifications that
59103 * are non-reporting. And we don't want them to show up after the
59104 * current Notification has been sent out. */
59105 UA_Notification *prev;
59106 while((prev = TAILQ_PREV(notification, NotificationQueue, localEntry))) {
59107 UA_Notification_delete(n: prev);
59108 }
59109
59110 /* Delete the notification, remove from the queues and decrease the counters */
59111 UA_Notification_delete(n: notification);
59112
59113 totalNotifications++;
59114 }
59115
59116 /* Set sizes */
59117 if(dcn) {
59118 dcn->monitoredItemsSize = dcnPos;
59119 if(dcnPos == 0) {
59120 UA_free(ptr: dcn->monitoredItems);
59121 dcn->monitoredItems = NULL;
59122 }
59123 }
59124
59125#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59126 if(enl) {
59127 enl->eventsSize = enlPos;
59128 if(enlPos == 0) {
59129 UA_free(ptr: enl->events);
59130 enl->events = NULL;
59131 }
59132 }
59133#endif
59134
59135 return UA_STATUSCODE_GOOD;
59136}
59137
59138/* According to OPC Unified Architecture, Part 4 5.13.1.1 i) The value 0 is
59139 * never used for the sequence number */
59140static UA_UInt32
59141UA_Subscription_nextSequenceNumber(UA_UInt32 sequenceNumber) {
59142 UA_UInt32 nextSequenceNumber = sequenceNumber + 1;
59143 if(nextSequenceNumber == 0)
59144 nextSequenceNumber = 1;
59145 return nextSequenceNumber;
59146}
59147
59148static void
59149publishCallback(UA_Server *server, UA_Subscription *sub) {
59150 UA_LOCK(&server->serviceMutex);
59151 UA_Subscription_sampleAndPublish(server, sub);
59152 UA_UNLOCK(&server->serviceMutex);
59153}
59154
59155static void
59156sendStatusChangeDelete(UA_Server *server, UA_Subscription *sub,
59157 UA_PublishResponseEntry *pre) {
59158 /* Cannot send out the StatusChange because no response is queued.
59159 * Delete the Subscription without sending the StatusChange. */
59160 if(!pre) {
59161 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59162 "Cannot send the StatusChange notification. "
59163 "Removing the subscription.");
59164 UA_Subscription_delete(server, sub);
59165 return;
59166 }
59167
59168 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59169 "Sending out a StatusChange "
59170 "notification and removing the subscription");
59171
59172 /* Populate the response */
59173 UA_PublishResponse *response = &pre->response;
59174
59175 UA_StatusChangeNotification scn;
59176 UA_StatusChangeNotification_init(p: &scn);
59177 scn.status = sub->statusChange;
59178
59179 UA_ExtensionObject notificationData;
59180 UA_ExtensionObject_setValue(eo: &notificationData, p: &scn,
59181 type: &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]);
59182
59183 response->responseHeader.timestamp = UA_DateTime_now();
59184 response->notificationMessage.notificationData = &notificationData;
59185 response->notificationMessage.notificationDataSize = 1;
59186 response->subscriptionId = sub->subscriptionId;
59187 response->notificationMessage.publishTime = response->responseHeader.timestamp;
59188 response->notificationMessage.sequenceNumber = sub->nextSequenceNumber;
59189
59190 /* Send the response */
59191 UA_assert(sub->session); /* Otherwise pre is NULL */
59192 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59193 "Sending out a publish response");
59194 sendResponse(server, session: sub->session, channel: sub->session->header.channel, requestId: pre->requestId,
59195 response: (UA_Response *)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
59196
59197 /* Clean up */
59198 response->notificationMessage.notificationData = NULL;
59199 response->notificationMessage.notificationDataSize = 0;
59200 UA_PublishResponse_clear(p: &pre->response);
59201 UA_free(ptr: pre);
59202
59203 /* Delete the subscription */
59204 UA_Subscription_delete(server, sub);
59205}
59206
59207/* Called every time we set the subscription late (or it is still late) */
59208static void
59209UA_Subscription_isLate(UA_Subscription *sub) {
59210 sub->state = UA_SUBSCRIPTIONSTATE_LATE;
59211#ifdef UA_ENABLE_DIAGNOSTICS
59212 sub->latePublishRequestCount++;
59213#endif
59214}
59215
59216/* Returns true if done */
59217UA_Boolean
59218UA_Subscription_publishOnce(UA_Server *server, UA_Subscription *sub) {
59219 /* Dequeue a response */
59220 UA_PublishResponseEntry *pre = NULL;
59221 if(sub->session)
59222 pre = UA_Session_dequeuePublishReq(session: sub->session);
59223
59224 /* Update the LifetimeCounter */
59225 if(pre) {
59226 sub->currentLifetimeCount = 0;
59227 } else {
59228 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59229 "The publish queue is empty");
59230 ++sub->currentLifetimeCount;
59231 if(sub->currentLifetimeCount > sub->lifeTimeCount) {
59232 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
59233 "End of subscription lifetime");
59234 /* Set the StatusChange to delete the subscription. */
59235 sub->statusChange = UA_STATUSCODE_BADTIMEOUT;
59236 }
59237 }
59238
59239 /* Send a StatusChange notification if possible and delete the
59240 * Subscription */
59241 if(sub->statusChange != UA_STATUSCODE_GOOD) {
59242 sendStatusChangeDelete(server, sub, pre);
59243 return true;
59244 }
59245
59246 /* Count the available notifications */
59247 UA_UInt32 notifications = (sub->publishingEnabled) ? sub->notificationQueueSize : 0;
59248 if(notifications > sub->notificationsPerPublish)
59249 notifications = sub->notificationsPerPublish;
59250
59251 /* Return if no notifications and no keepalive */
59252 if(notifications == 0) {
59253 ++sub->currentKeepAliveCount;
59254 if(sub->currentKeepAliveCount < sub->maxKeepAliveCount) {
59255 if(pre)
59256 UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */
59257 return true;
59258 }
59259 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub, "Sending a KeepAlive");
59260 }
59261
59262 /* We want to send a response, but cannot. Either because there is no queued
59263 * response or because the Subscription is detached from a Session or because
59264 * the SecureChannel for the Session is closed. */
59265 if(!pre || !sub->session || !sub->session->header.channel) {
59266 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59267 "Want to send a publish response but cannot. "
59268 "The subscription is late.");
59269 UA_Subscription_isLate(sub);
59270 if(pre)
59271 UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */
59272 return true;
59273 }
59274
59275 UA_assert(pre);
59276 UA_assert(sub->session); /* Otherwise pre is NULL */
59277
59278 /* Prepare the response */
59279 UA_PublishResponse *response = &pre->response;
59280 UA_NotificationMessage *message = &response->notificationMessage;
59281 UA_NotificationMessageEntry *retransmission = NULL;
59282#ifdef UA_ENABLE_DIAGNOSTICS
59283 size_t priorDataChangeNotifications = sub->dataChangeNotifications;
59284 size_t priorEventNotifications = sub->eventNotifications;
59285#endif
59286 if(notifications > 0) {
59287 if(server->config.enableRetransmissionQueue) {
59288 /* Allocate the retransmission entry */
59289 retransmission = (UA_NotificationMessageEntry*)
59290 UA_malloc(size: sizeof(UA_NotificationMessageEntry));
59291 if(!retransmission) {
59292 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
59293 "Could not allocate memory for retransmission. "
59294 "The subscription is late.");
59295
59296 UA_Subscription_isLate(sub);
59297 UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */
59298 return true;
59299 }
59300 }
59301
59302 /* Prepare the response */
59303 UA_StatusCode retval =
59304 prepareNotificationMessage(server, sub, message, maxNotifications: notifications);
59305 if(retval != UA_STATUSCODE_GOOD) {
59306 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
59307 "Could not prepare the notification message. "
59308 "The subscription is late.");
59309 /* If the retransmission queue is enabled a retransmission message is allocated */
59310 if(retransmission)
59311 UA_free(ptr: retransmission);
59312 UA_Subscription_isLate(sub);
59313 UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */
59314 return true;
59315 }
59316 }
59317
59318 /* <-- The point of no return --> */
59319
59320 /* Set up the response */
59321 response->responseHeader.timestamp = UA_DateTime_now();
59322 response->subscriptionId = sub->subscriptionId;
59323 response->moreNotifications = (sub->notificationQueueSize > 0);
59324 message->publishTime = response->responseHeader.timestamp;
59325
59326 /* Set sequence number to message. Started at 1 which is given during
59327 * creating a new subscription. The 1 is required for initial publish
59328 * response with or without an monitored item. */
59329 message->sequenceNumber = sub->nextSequenceNumber;
59330
59331 if(notifications > 0) {
59332 /* If the retransmission queue is enabled a retransmission message is
59333 * allocated */
59334 if(retransmission) {
59335 /* Put the notification message into the retransmission queue. This
59336 * needs to be done here, so that the message itself is included in
59337 * the available sequence numbers for acknowledgement. */
59338 retransmission->message = response->notificationMessage;
59339 UA_Subscription_addRetransmissionMessage(server, sub, entry: retransmission);
59340 }
59341 /* Only if a notification was created, the sequence number must be
59342 * increased. For a keepalive the sequence number can be reused. */
59343 sub->nextSequenceNumber =
59344 UA_Subscription_nextSequenceNumber(sequenceNumber: sub->nextSequenceNumber);
59345 }
59346
59347 /* Get the available sequence numbers from the retransmission queue */
59348 UA_assert(sub->retransmissionQueueSize <= UA_MAX_RETRANSMISSIONQUEUESIZE);
59349 UA_UInt32 seqNumbers[UA_MAX_RETRANSMISSIONQUEUESIZE];
59350 response->availableSequenceNumbers = seqNumbers;
59351 response->availableSequenceNumbersSize = sub->retransmissionQueueSize;
59352 size_t i = 0;
59353 UA_NotificationMessageEntry *nme;
59354 TAILQ_FOREACH(nme, &sub->retransmissionQueue, listEntry) {
59355 response->availableSequenceNumbers[i] = nme->message.sequenceNumber;
59356 ++i;
59357 }
59358 UA_assert(i == sub->retransmissionQueueSize);
59359
59360 /* Send the response */
59361 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59362 "Sending out a publish response with %" PRIu32
59363 " notifications", notifications);
59364 sendResponse(server, session: sub->session, channel: sub->session->header.channel, requestId: pre->requestId,
59365 response: (UA_Response*)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
59366
59367 /* Reset the Subscription state to NORMAL. But only if all notifications
59368 * have been sent out. Otherwise keep the Subscription in the LATE state. So
59369 * we immediately answer incoming Publish requests.
59370 *
59371 * (We also check that session->responseQueueSize > 0 in Service_Publish. To
59372 * avoid answering Publish requests out of order. As we additionally may
59373 * schedule an immediate next publishOnce if UA_Subscription_publishOnce
59374 * returns "not done".) */
59375 if(sub->notificationQueueSize == 0)
59376 sub->state = UA_SUBSCRIPTIONSTATE_NORMAL;
59377
59378 /* Reset the KeepAlive after publishing */
59379 sub->currentKeepAliveCount = 0;
59380
59381 /* Free the response */
59382 if(retransmission)
59383 /* NotificationMessage was moved into retransmission queue */
59384 UA_NotificationMessage_init(p: &response->notificationMessage);
59385 response->availableSequenceNumbers = NULL;
59386 response->availableSequenceNumbersSize = 0;
59387 UA_PublishResponse_clear(p: &pre->response);
59388 UA_free(ptr: pre);
59389
59390 /* Update the diagnostics statistics */
59391#ifdef UA_ENABLE_DIAGNOSTICS
59392 sub->publishRequestCount++;
59393
59394 UA_UInt32 sentDCN = (UA_UInt32)
59395 (priorDataChangeNotifications - sub->dataChangeNotifications);
59396 UA_UInt32 sentEN = (UA_UInt32)(priorEventNotifications - sub->eventNotifications);
59397 sub->dataChangeNotificationsCount += sentDCN;
59398 sub->eventNotificationsCount += sentEN;
59399 sub->notificationsCount += (sentDCN + sentEN);
59400#endif
59401
59402 /* Re-run publishing if notifications are remaining */
59403 return (sub->notificationQueueSize == 0);
59404}
59405
59406/* Repeat the main publishing callback until all notifications are sent out or
59407 * we have to stop */
59408void
59409UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) {
59410 UA_Boolean done = false;
59411 do {
59412 done = UA_Subscription_publishOnce(server, sub);
59413 } while(!done);
59414}
59415
59416void
59417UA_Subscription_sampleAndPublish(UA_Server *server, UA_Subscription *sub) {
59418 UA_LOCK_ASSERT(&server->serviceMutex, 1);
59419 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59420 "Sample and Publish Callback");
59421 UA_assert(sub);
59422
59423 /* Sample the MonitoredItems with sampling interval <0 (which implies
59424 * sampling in the same interval as the subscription) */
59425 UA_MonitoredItem *mon;
59426 LIST_FOREACH(mon, &sub->samplingMonitoredItems, sampling.samplingListEntry) {
59427 monitoredItem_sampleCallback(server, monitoredItem: mon);
59428 }
59429
59430 /* Publish the queued notifications */
59431 UA_Subscription_publish(server, sub);
59432}
59433
59434UA_Boolean
59435UA_Session_reachedPublishReqLimit(UA_Server *server, UA_Session *session) {
59436 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
59437 "Reached number of publish request limit");
59438
59439 /* Dequeue a response */
59440 UA_PublishResponseEntry *pre = UA_Session_dequeuePublishReq(session);
59441
59442 /* Cannot publish without a response */
59443 if(!pre) {
59444 UA_LOG_FATAL_SESSION(&server->config.logger, session,
59445 "No publish requests available");
59446 return false;
59447 }
59448
59449 /* <-- The point of no return --> */
59450
59451 UA_PublishResponse *response = &pre->response;
59452 UA_NotificationMessage *message = &response->notificationMessage;
59453
59454 /* Set up the response. Note that this response has no related subscription id */
59455 response->responseHeader.timestamp = UA_DateTime_now();
59456 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS;
59457 response->subscriptionId = 0;
59458 response->moreNotifications = false;
59459 message->publishTime = response->responseHeader.timestamp;
59460 message->sequenceNumber = 0;
59461 response->availableSequenceNumbersSize = 0;
59462
59463 /* Send the response */
59464 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
59465 "Sending out a publish response triggered by too many publish requests");
59466 sendResponse(server, session, channel: session->header.channel, requestId: pre->requestId,
59467 response: (UA_Response*)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
59468
59469 /* Free the response */
59470 UA_Array_delete(p: response->results, size: response->resultsSize, type: &UA_TYPES[UA_TYPES_UINT32]);
59471 UA_free(ptr: pre); /* no need for UA_PublishResponse_clear */
59472
59473 return true;
59474}
59475
59476UA_StatusCode
59477Subscription_registerPublishCallback(UA_Server *server, UA_Subscription *sub) {
59478 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59479 "Register subscription publishing callback");
59480 UA_LOCK_ASSERT(&server->serviceMutex, 1);
59481
59482 if(sub->publishCallbackId > 0)
59483 return UA_STATUSCODE_GOOD;
59484
59485 UA_StatusCode retval =
59486 addRepeatedCallback(server, callback: (UA_ServerCallback)publishCallback,
59487 data: sub, interval_ms: sub->publishingInterval, callbackId: &sub->publishCallbackId);
59488 if(retval != UA_STATUSCODE_GOOD)
59489 return retval;
59490
59491 UA_assert(sub->publishCallbackId > 0);
59492 return UA_STATUSCODE_GOOD;
59493}
59494
59495void
59496Subscription_unregisterPublishCallback(UA_Server *server, UA_Subscription *sub) {
59497 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59498 "Unregister subscription publishing callback");
59499
59500 if(sub->publishCallbackId == 0)
59501 return;
59502
59503 removeCallback(server, callbackId: sub->publishCallbackId);
59504 sub->publishCallbackId = 0;
59505}
59506
59507#endif /* UA_ENABLE_SUBSCRIPTIONS */
59508
59509/**** amalgamated original file "/src/server/ua_subscription_monitoreditem.c" ****/
59510
59511/* This Source Code Form is subject to the terms of the Mozilla Public
59512 * License, v. 2.0. If a copy of the MPL was not distributed with this
59513 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
59514 *
59515 * Copyright 2017-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
59516 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
59517 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
59518 * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
59519 * Copyright 2018 (c) Fabian Arndt, Root-Core
59520 * Copyright 2020-2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
59521 */
59522
59523
59524#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
59525
59526/****************/
59527/* Notification */
59528/****************/
59529
59530#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59531
59532static const UA_NodeId eventQueueOverflowEventType =
59533 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_EVENTQUEUEOVERFLOWEVENTTYPE}};
59534
59535/* The specification states in Part 4 5.12.1.5 that an EventQueueOverflowEvent
59536 * "is generated when the first Event has to be discarded [...] without
59537 * discarding any other event". So only generate one for all deleted events. */
59538static UA_StatusCode
59539createEventOverflowNotification(UA_Server *server, UA_Subscription *sub,
59540 UA_MonitoredItem *mon) {
59541 /* Avoid creating two adjacent overflow events */
59542 UA_Notification *indicator = NULL;
59543 if(mon->parameters.discardOldest) {
59544 indicator = TAILQ_FIRST(&mon->queue);
59545 UA_assert(indicator); /* must exist */
59546 if(indicator->isOverflowEvent)
59547 return UA_STATUSCODE_GOOD;
59548 } else {
59549 indicator = TAILQ_LAST(&mon->queue, NotificationQueue);
59550 UA_assert(indicator); /* must exist */
59551 /* Skip the last element. It is the recently added notification that
59552 * shall be kept. We know it is not an OverflowEvent. */
59553 UA_Notification *before = TAILQ_PREV(indicator, NotificationQueue, localEntry);
59554 if(before && before->isOverflowEvent)
59555 return UA_STATUSCODE_GOOD;
59556 }
59557
59558 /* A Notification is inserted into the queue which includes only the
59559 * NodeId of the OverflowEventType. */
59560
59561 /* Allocate the notification */
59562 UA_Notification *overflowNotification = UA_Notification_new();
59563 if(!overflowNotification)
59564 return UA_STATUSCODE_BADOUTOFMEMORY;
59565
59566 /* Set the notification fields */
59567 overflowNotification->isOverflowEvent = true;
59568 overflowNotification->mon = mon;
59569 overflowNotification->data.event.clientHandle = mon->parameters.clientHandle;
59570 overflowNotification->data.event.eventFields = UA_Variant_new();
59571 if(!overflowNotification->data.event.eventFields) {
59572 UA_free(ptr: overflowNotification);
59573 return UA_STATUSCODE_BADOUTOFMEMORY;
59574 }
59575 overflowNotification->data.event.eventFieldsSize = 1;
59576 UA_StatusCode retval =
59577 UA_Variant_setScalarCopy(v: overflowNotification->data.event.eventFields,
59578 p: &eventQueueOverflowEventType, type: &UA_TYPES[UA_TYPES_NODEID]);
59579 if(retval != UA_STATUSCODE_GOOD) {
59580 UA_Notification_delete(n: overflowNotification);
59581 return retval;
59582 }
59583
59584 /* Insert before the removed notification. This is either first in the
59585 * queue (if the oldest notification was removed) or before the new event
59586 * that remains the last element of the queue.
59587 *
59588 * Ensure that the following is consistent with UA_Notification_enqueueMon
59589 * and UA_Notification_enqueueSub! */
59590 TAILQ_INSERT_BEFORE(indicator, overflowNotification, localEntry);
59591 ++mon->eventOverflows;
59592 ++mon->queueSize;
59593
59594 /* Test for consistency */
59595 UA_assert(mon->queueSize >= mon->eventOverflows);
59596 UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
59597
59598 if(TAILQ_NEXT(indicator, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
59599 /* Insert just before the indicator */
59600 TAILQ_INSERT_BEFORE(indicator, overflowNotification, globalEntry);
59601 } else {
59602 /* The indicator was not reporting or not added yet. */
59603 if(!mon->parameters.discardOldest) {
59604 /* Add last to the per-Subscription queue */
59605 TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue,
59606 overflowNotification, globalEntry);
59607 } else {
59608 /* Find the oldest reported element. Add before that. */
59609 while(indicator) {
59610 indicator = TAILQ_PREV(indicator, NotificationQueue, localEntry);
59611 if(!indicator) {
59612 TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue,
59613 overflowNotification, globalEntry);
59614 break;
59615 }
59616 if(TAILQ_NEXT(indicator, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
59617 TAILQ_INSERT_BEFORE(indicator, overflowNotification, globalEntry);
59618 break;
59619 }
59620 }
59621 }
59622 }
59623
59624 ++sub->notificationQueueSize;
59625 ++sub->eventNotifications;
59626
59627 /* Update the diagnostics statistics */
59628#ifdef UA_ENABLE_DIAGNOSTICS
59629 sub->eventQueueOverFlowCount++;
59630#endif
59631
59632 return UA_STATUSCODE_GOOD;
59633}
59634
59635#endif
59636
59637/* Set the InfoBits that a datachange notification was removed */
59638static void
59639setOverflowInfoBits(UA_MonitoredItem *mon) {
59640 /* Only for queues with more than one element */
59641 if(mon->parameters.queueSize == 1)
59642 return;
59643
59644 UA_Notification *indicator = NULL;
59645 if(mon->parameters.discardOldest) {
59646 indicator = TAILQ_FIRST(&mon->queue);
59647 } else {
59648 indicator = TAILQ_LAST(&mon->queue, NotificationQueue);
59649 }
59650 UA_assert(indicator); /* must exist */
59651
59652 indicator->data.dataChange.value.hasStatus = true;
59653 indicator->data.dataChange.value.status |=
59654 (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW);
59655}
59656
59657/* Remove the InfoBits when the queueSize was reduced to 1 */
59658void
59659UA_MonitoredItem_removeOverflowInfoBits(UA_MonitoredItem *mon) {
59660 /* Don't consider queue size > 1 and Event MonitoredItems */
59661 if(mon->parameters.queueSize > 1 ||
59662 mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
59663 return;
59664
59665 /* Get the first notification */
59666 UA_Notification *n = TAILQ_FIRST(&mon->queue);
59667 if(!n)
59668 return;
59669
59670 /* Assertion that at most one notification is in the queue */
59671 UA_assert(n == TAILQ_LAST(&mon->queue, NotificationQueue));
59672
59673 /* Remve the Infobits */
59674 n->data.dataChange.value.status &= ~(UA_StatusCode)
59675 (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW);
59676}
59677
59678UA_Notification *
59679UA_Notification_new(void) {
59680 UA_Notification *n = (UA_Notification*)UA_calloc(nmemb: 1, size: sizeof(UA_Notification));
59681 if(n) {
59682 /* Set the sentinel for a notification that is not enqueued */
59683 TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
59684 TAILQ_NEXT(n, localEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
59685 }
59686 return n;
59687}
59688
59689static void UA_Notification_dequeueMon(UA_Notification *n);
59690static void UA_Notification_enqueueSub(UA_Notification *n);
59691static void UA_Notification_dequeueSub(UA_Notification *n);
59692
59693void
59694UA_Notification_delete(UA_Notification *n) {
59695 UA_assert(n != UA_SUBSCRIPTION_QUEUE_SENTINEL);
59696 if(n->mon) {
59697 UA_Notification_dequeueMon(n);
59698 UA_Notification_dequeueSub(n);
59699 switch(n->mon->itemToMonitor.attributeId) {
59700#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59701 case UA_ATTRIBUTEID_EVENTNOTIFIER:
59702 UA_EventFieldList_clear(p: &n->data.event);
59703 UA_EventFilterResult_clear(p: &n->result);
59704 break;
59705#endif
59706 default:
59707 UA_MonitoredItemNotification_clear(p: &n->data.dataChange);
59708 break;
59709 }
59710 }
59711 UA_free(ptr: n);
59712}
59713
59714/* Add to the MonitoredItem queue, update all counters and then handle overflow */
59715static void
59716UA_Notification_enqueueMon(UA_Server *server, UA_Notification *n) {
59717 UA_MonitoredItem *mon = n->mon;
59718 UA_assert(mon);
59719 UA_assert(TAILQ_NEXT(n, localEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL);
59720
59721 /* Add to the MonitoredItem */
59722 TAILQ_INSERT_TAIL(&mon->queue, n, localEntry);
59723 ++mon->queueSize;
59724
59725#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59726 if(n->isOverflowEvent)
59727 ++mon->eventOverflows;
59728#endif
59729
59730 /* Test for consistency */
59731 UA_assert(mon->queueSize >= mon->eventOverflows);
59732 UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
59733
59734 /* Ensure enough space is available in the MonitoredItem. Do this only after
59735 * adding the new Notification. */
59736 UA_MonitoredItem_ensureQueueSpace(server, mon);
59737
59738 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, mon->subscription,
59739 "MonitoredItem %" PRIi32 " | "
59740 "Notification enqueued (Queue size %lu / %lu)",
59741 mon->monitoredItemId,
59742 (long unsigned)mon->queueSize,
59743 (long unsigned)mon->parameters.queueSize);
59744}
59745
59746void
59747UA_Notification_enqueueSub(UA_Notification *n) {
59748 UA_MonitoredItem *mon = n->mon;
59749 UA_assert(mon);
59750
59751 UA_Subscription *sub = mon->subscription;
59752 UA_assert(sub);
59753
59754 if(TAILQ_NEXT(n, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL)
59755 return;
59756
59757 /* Add to the subscription if reporting is enabled */
59758 TAILQ_INSERT_TAIL(&sub->notificationQueue, n, globalEntry);
59759 ++sub->notificationQueueSize;
59760
59761 switch(mon->itemToMonitor.attributeId) {
59762#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59763 case UA_ATTRIBUTEID_EVENTNOTIFIER:
59764 ++sub->eventNotifications;
59765 break;
59766#endif
59767 default:
59768 ++sub->dataChangeNotifications;
59769 break;
59770 }
59771}
59772
59773void
59774UA_Notification_enqueueAndTrigger(UA_Server *server, UA_Notification *n) {
59775 UA_MonitoredItem *mon = n->mon;
59776 UA_Subscription *sub = mon->subscription;
59777 UA_assert(sub); /* This function is never called for local MonitoredItems */
59778
59779 /* If reporting or (sampled+triggered), enqueue into the Subscription first
59780 * and then into the MonitoredItem. UA_MonitoredItem_ensureQueueSpace
59781 * (called within UA_Notification_enqueueMon) assumes the notification is
59782 * already in the Subscription's publishing queue. */
59783 if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING ||
59784 (mon->monitoringMode == UA_MONITORINGMODE_SAMPLING &&
59785 mon->triggeredUntil > UA_DateTime_nowMonotonic())) {
59786 UA_Notification_enqueueSub(n);
59787 mon->triggeredUntil = UA_INT64_MIN;
59788 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, mon->subscription,
59789 "Notification enqueued (Queue size %lu)",
59790 (long unsigned)mon->subscription->notificationQueueSize);
59791 }
59792
59793 /* Insert into the MonitoredItem. This checks the queue size and
59794 * handles overflow. */
59795 UA_Notification_enqueueMon(server, n);
59796
59797 for(size_t i = mon->triggeringLinksSize - 1; i < mon->triggeringLinksSize; i--) {
59798 /* Get the triggered MonitoredItem. Remove the link if the MI doesn't exist. */
59799 UA_MonitoredItem *triggeredMon =
59800 UA_Subscription_getMonitoredItem(sub, monitoredItemId: mon->triggeringLinks[i]);
59801 if(!triggeredMon) {
59802 UA_MonitoredItem_removeLink(sub, mon, linkId: mon->triggeringLinks[i]);
59803 continue;
59804 }
59805
59806 /* Only sampling MonitoredItems receive a trigger. Reporting
59807 * MonitoredItems send out Notifications anyway and disabled
59808 * MonitoredItems don't create samples to send. */
59809 if(triggeredMon->monitoringMode != UA_MONITORINGMODE_SAMPLING)
59810 continue;
59811
59812 /* Get the latest sampled Notification from the triggered MonitoredItem.
59813 * Enqueue for publication. */
59814 UA_Notification *n2 = TAILQ_LAST(&triggeredMon->queue, NotificationQueue);
59815 if(n2)
59816 UA_Notification_enqueueSub(n: n2);
59817
59818 /* The next Notification within the publishing interval is going to be
59819 * published as well. (Falsely) assume that the publishing cycle has
59820 * started right now, so that we don't have to loop over MonitoredItems
59821 * to deactivate the triggering after the publishing cycle. */
59822 triggeredMon->triggeredUntil = UA_DateTime_nowMonotonic() +
59823 (UA_DateTime)(sub->publishingInterval * (UA_Double)UA_DATETIME_MSEC);
59824
59825 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59826 "MonitoredItem %u triggers MonitoredItem %u",
59827 mon->monitoredItemId, triggeredMon->monitoredItemId);
59828 }
59829}
59830
59831/* Remove from the MonitoredItem queue and adjust all counters */
59832static void
59833UA_Notification_dequeueMon(UA_Notification *n) {
59834 UA_MonitoredItem *mon = n->mon;
59835 UA_assert(mon);
59836
59837 if(TAILQ_NEXT(n, localEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL)
59838 return;
59839
59840 /* Remove from the MonitoredItem queue */
59841#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59842 if(n->isOverflowEvent)
59843 --mon->eventOverflows;
59844#endif
59845
59846 TAILQ_REMOVE(&mon->queue, n, localEntry);
59847 --mon->queueSize;
59848
59849 /* Test for consistency */
59850 UA_assert(mon->queueSize >= mon->eventOverflows);
59851 UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
59852
59853 /* Reset the sentintel */
59854 TAILQ_NEXT(n, localEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
59855}
59856
59857void
59858UA_Notification_dequeueSub(UA_Notification *n) {
59859 if(TAILQ_NEXT(n, globalEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL)
59860 return;
59861
59862 UA_MonitoredItem *mon = n->mon;
59863 UA_assert(mon);
59864 UA_Subscription *sub = mon->subscription;
59865 UA_assert(sub);
59866
59867 switch(mon->itemToMonitor.attributeId) {
59868#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59869 case UA_ATTRIBUTEID_EVENTNOTIFIER:
59870 --sub->eventNotifications;
59871 break;
59872#endif
59873 default:
59874 --sub->dataChangeNotifications;
59875 break;
59876 }
59877
59878 TAILQ_REMOVE(&sub->notificationQueue, n, globalEntry);
59879 --sub->notificationQueueSize;
59880
59881 /* Reset the sentinel */
59882 TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
59883}
59884
59885/*****************/
59886/* MonitoredItem */
59887/*****************/
59888
59889void
59890UA_MonitoredItem_init(UA_MonitoredItem *mon) {
59891 memset(s: mon, c: 0, n: sizeof(UA_MonitoredItem));
59892 TAILQ_INIT(&mon->queue);
59893 mon->triggeredUntil = UA_INT64_MIN;
59894}
59895
59896static UA_StatusCode
59897addMonitoredItemBackpointer(UA_Server *server, UA_Session *session,
59898 UA_Node *node, void *data) {
59899 UA_MonitoredItem *mon = (UA_MonitoredItem*)data;
59900 UA_assert(mon != (UA_MonitoredItem*)~0);
59901 mon->sampling.nodeListNext = node->head.monitoredItems;
59902 node->head.monitoredItems = mon;
59903 return UA_STATUSCODE_GOOD;
59904}
59905
59906static UA_StatusCode
59907removeMonitoredItemBackPointer(UA_Server *server, UA_Session *session,
59908 UA_Node *node, void *data) {
59909 if(!node->head.monitoredItems)
59910 return UA_STATUSCODE_GOOD;
59911
59912 /* Edge case that it's the first element */
59913 UA_MonitoredItem *remove = (UA_MonitoredItem*)data;
59914 if(node->head.monitoredItems == remove) {
59915 node->head.monitoredItems = remove->sampling.nodeListNext;
59916 return UA_STATUSCODE_GOOD;
59917 }
59918
59919 UA_MonitoredItem *prev = node->head.monitoredItems;
59920 UA_MonitoredItem *entry = prev->sampling.nodeListNext;
59921 for(; entry != NULL; prev = entry, entry = entry->sampling.nodeListNext) {
59922 if(entry == remove) {
59923 prev->sampling.nodeListNext = entry->sampling.nodeListNext;
59924 break;
59925 }
59926 }
59927
59928 return UA_STATUSCODE_GOOD;
59929}
59930
59931void
59932UA_Server_registerMonitoredItem(UA_Server *server, UA_MonitoredItem *mon) {
59933 if(mon->registered)
59934 return;
59935
59936 /* Register in Subscription and Server */
59937 UA_Subscription *sub = mon->subscription;
59938 if(sub) {
59939 mon->monitoredItemId = ++sub->lastMonitoredItemId;
59940 mon->subscription = sub;
59941 sub->monitoredItemsSize++;
59942 LIST_INSERT_HEAD(&sub->monitoredItems, mon, listEntry);
59943 } else {
59944 mon->monitoredItemId = ++server->lastLocalMonitoredItemId;
59945 LIST_INSERT_HEAD(&server->localMonitoredItems, mon, listEntry);
59946 }
59947 server->monitoredItemsSize++;
59948
59949 /* Register the MonitoredItem in userland */
59950 if(server->config.monitoredItemRegisterCallback) {
59951 UA_Session *session = &server->adminSession;
59952 if(sub)
59953 session = sub->session;
59954
59955 void *targetContext = NULL;
59956 getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &targetContext);
59957 UA_UNLOCK(&server->serviceMutex);
59958 server->config.monitoredItemRegisterCallback(server,
59959 session ? &session->sessionId : NULL,
59960 session ? session->sessionHandle : NULL,
59961 &mon->itemToMonitor.nodeId,
59962 targetContext,
59963 mon->itemToMonitor.attributeId, false);
59964 UA_LOCK(&server->serviceMutex);
59965 }
59966
59967 mon->registered = true;
59968}
59969
59970static void
59971UA_Server_unregisterMonitoredItem(UA_Server *server, UA_MonitoredItem *mon) {
59972 if(!mon->registered)
59973 return;
59974
59975 UA_Subscription *sub = mon->subscription;
59976 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
59977 "MonitoredItem %" PRIi32 " | Deleting the MonitoredItem",
59978 mon->monitoredItemId);
59979
59980 /* Deregister MonitoredItem in userland */
59981 if(server->config.monitoredItemRegisterCallback) {
59982 UA_Session *session = &server->adminSession;
59983 if(sub)
59984 session = sub->session;
59985
59986 void *targetContext = NULL;
59987 getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &targetContext);
59988 UA_UNLOCK(&server->serviceMutex);
59989 server->config.monitoredItemRegisterCallback(server,
59990 session ? &session->sessionId : NULL,
59991 session ? session->sessionHandle : NULL,
59992 &mon->itemToMonitor.nodeId,
59993 targetContext,
59994 mon->itemToMonitor.attributeId, true);
59995 UA_LOCK(&server->serviceMutex);
59996 }
59997
59998 /* Deregister in Subscription and server */
59999 if(sub)
60000 sub->monitoredItemsSize--;
60001 LIST_REMOVE(mon, listEntry); /* Also for LocalMonitoredItems */
60002 server->monitoredItemsSize--;
60003
60004 mon->registered = false;
60005}
60006
60007UA_StatusCode
60008UA_MonitoredItem_setMonitoringMode(UA_Server *server, UA_MonitoredItem *mon,
60009 UA_MonitoringMode monitoringMode) {
60010 /* Check if the MonitoringMode is valid or not */
60011 if(monitoringMode > UA_MONITORINGMODE_REPORTING)
60012 return UA_STATUSCODE_BADMONITORINGMODEINVALID;
60013
60014 /* Set the MonitoringMode, store the old mode */
60015 UA_MonitoringMode oldMode = mon->monitoringMode;
60016 mon->monitoringMode = monitoringMode;
60017
60018 UA_Notification *notification;
60019 /* Reporting is disabled. This causes all Notifications to be dequeued and
60020 * deleted. Also remove the last samples so that we immediately generate a
60021 * Notification when re-activated. */
60022 if(mon->monitoringMode == UA_MONITORINGMODE_DISABLED) {
60023 UA_Notification *notification_tmp;
60024 UA_MonitoredItem_unregisterSampling(server, mon);
60025 TAILQ_FOREACH_SAFE(notification, &mon->queue, localEntry, notification_tmp) {
60026 UA_Notification_delete(n: notification);
60027 }
60028 UA_DataValue_clear(p: &mon->lastValue);
60029 return UA_STATUSCODE_GOOD;
60030 }
60031
60032 /* When reporting is enabled, put all notifications that were already
60033 * sampled into the global queue of the subscription. When sampling is
60034 * enabled, remove all notifications from the global queue. !!! This needs
60035 * to be the same operation as in UA_Notification_enqueue !!! */
60036 if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING) {
60037 /* Make all notifications reporting. Re-enqueue to ensure they have the
60038 * right order if some notifications are already reported by a trigger
60039 * link. */
60040 TAILQ_FOREACH(notification, &mon->queue, localEntry) {
60041 UA_Notification_dequeueSub(n: notification);
60042 UA_Notification_enqueueSub(n: notification);
60043 }
60044 } else /* mon->monitoringMode == UA_MONITORINGMODE_SAMPLING */ {
60045 /* Make all notifications non-reporting */
60046 TAILQ_FOREACH(notification, &mon->queue, localEntry)
60047 UA_Notification_dequeueSub(n: notification);
60048 }
60049
60050 /* Register the sampling callback with an interval. If registering the
60051 * sampling callback failed, set to disabled. But don't delete the current
60052 * notifications. */
60053 UA_StatusCode res = UA_MonitoredItem_registerSampling(server, mon);
60054 if(res != UA_STATUSCODE_GOOD) {
60055 mon->monitoringMode = UA_MONITORINGMODE_DISABLED;
60056 return res;
60057 }
60058
60059 /* Manually create the first sample if the MonitoredItem was disabled, the
60060 * MonitoredItem is now sampling (or reporting) and it is not an
60061 * Event-MonitoredItem */
60062 if(oldMode == UA_MONITORINGMODE_DISABLED &&
60063 mon->monitoringMode > UA_MONITORINGMODE_DISABLED &&
60064 mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
60065 monitoredItem_sampleCallback(server, monitoredItem: mon);
60066
60067 return UA_STATUSCODE_GOOD;
60068}
60069
60070void
60071UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *mon) {
60072 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60073
60074 /* Remove the sampling callback */
60075 UA_MonitoredItem_unregisterSampling(server, mon);
60076
60077 /* Deregister in Server and Subscription */
60078 if(mon->registered)
60079 UA_Server_unregisterMonitoredItem(server, mon);
60080
60081 /* Remove the TriggeringLinks */
60082 if(mon->triggeringLinksSize > 0) {
60083 UA_free(ptr: mon->triggeringLinks);
60084 mon->triggeringLinks = NULL;
60085 mon->triggeringLinksSize = 0;
60086 }
60087
60088 /* Remove the queued notifications attached to the subscription */
60089 UA_Notification *notification, *notification_tmp;
60090 TAILQ_FOREACH_SAFE(notification, &mon->queue, localEntry, notification_tmp) {
60091 UA_Notification_delete(n: notification);
60092 }
60093
60094 /* Remove the settings */
60095 UA_ReadValueId_clear(p: &mon->itemToMonitor);
60096 UA_MonitoringParameters_clear(p: &mon->parameters);
60097
60098 /* Remove the last samples */
60099 UA_DataValue_clear(p: &mon->lastValue);
60100
60101 /* Add a delayed callback to remove the MonitoredItem when the current jobs
60102 * have completed. This is needed to allow that a local MonitoredItem can
60103 * remove itself in the callback. */
60104 mon->delayedFreePointers.callback = NULL;
60105 mon->delayedFreePointers.application = server;
60106 mon->delayedFreePointers.data = NULL;
60107 mon->delayedFreePointers.nextTime = UA_DateTime_nowMonotonic() + 1;
60108 mon->delayedFreePointers.interval = 0;
60109 UA_Timer_addTimerEntry(t: &server->timer, te: &mon->delayedFreePointers, NULL);
60110}
60111
60112void
60113UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
60114 /* There can be only one EventOverflow more than normal entries. Because
60115 * EventOverflows are never adjacent. */
60116 UA_assert(mon->queueSize >= mon->eventOverflows);
60117 UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
60118
60119 /* Always attached to a Subscription (no local MonitoredItem) */
60120 UA_Subscription *sub = mon->subscription;
60121 UA_assert(sub);
60122
60123 /* Nothing to do */
60124 if(mon->queueSize - mon->eventOverflows <= mon->parameters.queueSize)
60125 return;
60126
60127 /* Remove notifications until the required queue size is reached */
60128 UA_Boolean reporting = false;
60129 size_t remove = mon->queueSize - mon->eventOverflows - mon->parameters.queueSize;
60130 while(remove > 0) {
60131 /* The minimum queue size (without EventOverflows) is 1. At least two
60132 * notifications that are not EventOverflows are in the queue. */
60133 UA_assert(mon->queueSize - mon->eventOverflows >= 2);
60134
60135 /* Select the next notification to delete. Skip over overflow events. */
60136 UA_Notification *del = NULL;
60137 if(mon->parameters.discardOldest) {
60138 /* Remove the oldest */
60139 del = TAILQ_FIRST(&mon->queue);
60140#if defined(UA_ENABLE_SUBSCRIPTIONS_EVENTS) && !defined(__clang_analyzer__)
60141 while(del->isOverflowEvent)
60142 del = TAILQ_NEXT(del, localEntry); /* skip overflow events */
60143#endif
60144 } else {
60145 /* Remove the second newest (to keep the up-to-date notification).
60146 * The last entry is not an OverflowEvent -- we just added it. */
60147 del = TAILQ_LAST(&mon->queue, NotificationQueue);
60148 del = TAILQ_PREV(del, NotificationQueue, localEntry);
60149#if defined(UA_ENABLE_SUBSCRIPTIONS_EVENTS) && !defined(__clang_analyzer__)
60150 while(del->isOverflowEvent)
60151 del = TAILQ_PREV(del, NotificationQueue, localEntry); /* skip overflow events */
60152#endif
60153 }
60154
60155 UA_assert(del); /* There must have been one entry that can be deleted */
60156
60157 /* Only create OverflowEvents (and set InfoBits) if the notification
60158 * that is removed is reported */
60159 if(TAILQ_NEXT(del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL)
60160 reporting = true;
60161
60162 /* Move the entry after del in the per-MonitoredItem queue right after
60163 * del in the per-Subscription queue. So we don't starve MonitoredItems
60164 * with a high sampling interval in the Subscription queue by always
60165 * removing their first appearance in the per-Subscription queue.
60166 *
60167 * With MonitoringMode == SAMPLING, the Notifications are not (all) in
60168 * the per-Subscription queue. Don't reinsert in that case.
60169 *
60170 * For the reinsertion to work, first insert into the per-Subscription
60171 * queue. */
60172 if(TAILQ_NEXT(del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
60173 UA_Notification *after_del = TAILQ_NEXT(del, localEntry);
60174 UA_assert(after_del); /* There must be one remaining element after del */
60175 if(TAILQ_NEXT(after_del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
60176 TAILQ_REMOVE(&sub->notificationQueue, after_del, globalEntry);
60177 TAILQ_INSERT_AFTER(&sub->notificationQueue, del, after_del, globalEntry);
60178 }
60179 }
60180
60181 remove--;
60182
60183 /* Delete the notification and remove it from the queues */
60184 UA_Notification_delete(n: del);
60185
60186 /* Update the subscription diagnostics statistics */
60187#ifdef UA_ENABLE_DIAGNOSTICS
60188 sub->monitoringQueueOverflowCount++;
60189#endif
60190
60191 /* Assertions to help Clang's scan-analyzer */
60192 UA_assert(del != TAILQ_FIRST(&mon->queue));
60193 UA_assert(del != TAILQ_LAST(&mon->queue, NotificationQueue));
60194 UA_assert(del != TAILQ_PREV(TAILQ_LAST(&mon->queue, NotificationQueue),
60195 NotificationQueue, localEntry));
60196 }
60197
60198 /* Leave an entry to indicate that notifications were removed */
60199 if(reporting) {
60200#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
60201 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
60202 createEventOverflowNotification(server, sub, mon);
60203 else
60204#endif
60205 setOverflowInfoBits(mon);
60206 }
60207}
60208
60209UA_StatusCode
60210UA_MonitoredItem_registerSampling(UA_Server *server, UA_MonitoredItem *mon) {
60211 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60212
60213 /* Sampling is already registered */
60214 if(mon->samplingType != UA_MONITOREDITEMSAMPLINGTYPE_NONE)
60215 return UA_STATUSCODE_GOOD;
60216
60217 UA_StatusCode res = UA_STATUSCODE_GOOD;
60218 UA_Subscription *sub = mon->subscription;
60219 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER ||
60220 mon->parameters.samplingInterval == 0.0) {
60221 /* Add to the linked list in the node */
60222 UA_Session *session = &server->adminSession;
60223 if(sub)
60224 session = sub->session;
60225 res = UA_Server_editNode(server, session, nodeId: &mon->itemToMonitor.nodeId,
60226 callback: addMonitoredItemBackpointer, data: mon);
60227 if(res == UA_STATUSCODE_GOOD)
60228 mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_EVENT;
60229 return res;
60230 } else if(mon->parameters.samplingInterval < 0.0) {
60231 /* Add to the subscription for sampling before every publish */
60232 if(!sub)
60233 return UA_STATUSCODE_BADINTERNALERROR; /* Not possible for local MonitoredItems */
60234 LIST_INSERT_HEAD(&sub->samplingMonitoredItems, mon, sampling.samplingListEntry);
60235 mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_PUBLISH;
60236 } else {
60237 /* DataChange MonitoredItems with a positive sampling interval have a
60238 * repeated callback. Other MonitoredItems are attached to the Node in a
60239 * linked list of backpointers. */
60240 res = addRepeatedCallback(server,
60241 callback: (UA_ServerCallback)UA_MonitoredItem_sampleCallback,
60242 data: mon, interval_ms: mon->parameters.samplingInterval,
60243 callbackId: &mon->sampling.callbackId);
60244 if(res == UA_STATUSCODE_GOOD)
60245 mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_CYCLIC;
60246 }
60247
60248 return res;
60249}
60250
60251void
60252UA_MonitoredItem_unregisterSampling(UA_Server *server, UA_MonitoredItem *mon) {
60253 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60254
60255 switch(mon->samplingType) {
60256 case UA_MONITOREDITEMSAMPLINGTYPE_CYCLIC:
60257 /* Remove repeated callback */
60258 removeCallback(server, callbackId: mon->sampling.callbackId);
60259 break;
60260
60261 case UA_MONITOREDITEMSAMPLINGTYPE_EVENT: {
60262 /* Added to a node */
60263 UA_Subscription *sub = mon->subscription;
60264 UA_Session *session = &server->adminSession;
60265 if(sub)
60266 session = sub->session;
60267 UA_Server_editNode(server, session, nodeId: &mon->itemToMonitor.nodeId,
60268 callback: removeMonitoredItemBackPointer, data: mon);
60269 break;
60270 }
60271
60272 case UA_MONITOREDITEMSAMPLINGTYPE_PUBLISH:
60273 /* Added to the subscription */
60274 LIST_REMOVE(mon, sampling.samplingListEntry);
60275 break;
60276
60277 case UA_MONITOREDITEMSAMPLINGTYPE_NONE:
60278 default:
60279 /* Sampling is not registered */
60280 break;
60281 }
60282
60283 mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_NONE;
60284}
60285
60286UA_StatusCode
60287UA_MonitoredItem_removeLink(UA_Subscription *sub, UA_MonitoredItem *mon, UA_UInt32 linkId) {
60288 /* Find the index */
60289 size_t i = 0;
60290 for(; i < mon->triggeringLinksSize; i++) {
60291 if(mon->triggeringLinks[i] == linkId)
60292 break;
60293 }
60294
60295 /* Not existing / already removed */
60296 if(i == mon->triggeringLinksSize)
60297 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
60298
60299 /* Remove the link */
60300 mon->triggeringLinksSize--;
60301 if(mon->triggeringLinksSize == 0) {
60302 UA_free(ptr: mon->triggeringLinks);
60303 mon->triggeringLinks = NULL;
60304 } else {
60305 mon->triggeringLinks[i] = mon->triggeringLinks[mon->triggeringLinksSize];
60306 UA_UInt32 *tmpLinks = (UA_UInt32*)
60307 UA_realloc(ptr: mon->triggeringLinks, size: mon->triggeringLinksSize * sizeof(UA_UInt32));
60308 if(tmpLinks)
60309 mon->triggeringLinks = tmpLinks;
60310 }
60311
60312 /* Does the target MonitoredItem exist? This is stupid, but the CTT wants us
60313 * to to this. We don't auto-remove links together with the target
60314 * MonitoredItem. Links to removed MonitoredItems are removed when the link
60315 * triggers and the target no longer exists. */
60316 UA_MonitoredItem *mon2 = UA_Subscription_getMonitoredItem(sub, monitoredItemId: linkId);
60317 if(!mon2)
60318 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
60319
60320 return UA_STATUSCODE_GOOD;
60321}
60322
60323UA_StatusCode
60324UA_MonitoredItem_addLink(UA_Subscription *sub, UA_MonitoredItem *mon, UA_UInt32 linkId) {
60325 /* Does the target MonitoredItem exist? */
60326 UA_MonitoredItem *mon2 = UA_Subscription_getMonitoredItem(sub, monitoredItemId: linkId);
60327 if(!mon2)
60328 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
60329
60330 /* Does the link already exist? */
60331 for(size_t i = 0 ; i < mon->triggeringLinksSize; i++) {
60332 if(mon->triggeringLinks[i] == linkId)
60333 return UA_STATUSCODE_GOOD;
60334 }
60335
60336 /* Allocate the memory */
60337 UA_UInt32 *tmpLinkIds = (UA_UInt32*)
60338 UA_realloc(ptr: mon->triggeringLinks, size: (mon->triggeringLinksSize + 1) * sizeof(UA_UInt32));
60339 if(!tmpLinkIds)
60340 return UA_STATUSCODE_BADOUTOFMEMORY;
60341 mon->triggeringLinks = tmpLinkIds;
60342
60343 /* Add the link */
60344 mon->triggeringLinks[mon->triggeringLinksSize] = linkId;
60345 mon->triggeringLinksSize++;
60346 return UA_STATUSCODE_GOOD;
60347}
60348
60349#endif /* UA_ENABLE_SUBSCRIPTIONS */
60350
60351/**** amalgamated original file "/src/server/ua_subscription_datachange.c" ****/
60352
60353/* This Source Code Form is subject to the terms of the Mozilla Public
60354 * License, v. 2.0. If a copy of the MPL was not distributed with this
60355 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
60356 *
60357 * Copyright 2017-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
60358 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
60359 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
60360 * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
60361 * Copyright 2018 (c) Fabian Arndt, Root-Core
60362 */
60363
60364
60365#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
60366
60367/* Detect value changes outside the deadband */
60368#define UA_DETECT_DEADBAND(TYPE) do { \
60369 TYPE v1 = *(const TYPE*)data1; \
60370 TYPE v2 = *(const TYPE*)data2; \
60371 TYPE diff = (v1 > v2) ? (TYPE)(v1 - v2) : (TYPE)(v2 - v1); \
60372 return ((UA_Double)diff > deadband); \
60373} while(false);
60374
60375static UA_Boolean
60376detectScalarDeadBand(const void *data1, const void *data2,
60377 const UA_DataType *type, const UA_Double deadband) {
60378 if(type->typeKind == UA_DATATYPEKIND_SBYTE) {
60379 UA_DETECT_DEADBAND(UA_SByte);
60380 } else if(type->typeKind == UA_DATATYPEKIND_BYTE) {
60381 UA_DETECT_DEADBAND(UA_Byte);
60382 } else if(type->typeKind == UA_DATATYPEKIND_INT16) {
60383 UA_DETECT_DEADBAND(UA_Int16);
60384 } else if(type->typeKind == UA_DATATYPEKIND_UINT16) {
60385 UA_DETECT_DEADBAND(UA_UInt16);
60386 } else if(type->typeKind == UA_DATATYPEKIND_INT32) {
60387 UA_DETECT_DEADBAND(UA_Int32);
60388 } else if(type->typeKind == UA_DATATYPEKIND_UINT32) {
60389 UA_DETECT_DEADBAND(UA_UInt32);
60390 } else if(type->typeKind == UA_DATATYPEKIND_INT64) {
60391 UA_DETECT_DEADBAND(UA_Int64);
60392 } else if(type->typeKind == UA_DATATYPEKIND_UINT64) {
60393 UA_DETECT_DEADBAND(UA_UInt64);
60394 } else if(type->typeKind == UA_DATATYPEKIND_FLOAT) {
60395 UA_DETECT_DEADBAND(UA_Float);
60396 } else if(type->typeKind == UA_DATATYPEKIND_DOUBLE) {
60397 UA_DETECT_DEADBAND(UA_Double);
60398 } else {
60399 return false; /* Not a known numerical type */
60400 }
60401}
60402
60403static UA_Boolean
60404detectVariantDeadband(const UA_Variant *value, const UA_Variant *oldValue,
60405 const UA_Double deadbandValue) {
60406 if(value->arrayLength != oldValue->arrayLength)
60407 return true;
60408 if(value->type != oldValue->type)
60409 return true;
60410 size_t length = 1;
60411 if(!UA_Variant_isScalar(v: value))
60412 length = value->arrayLength;
60413 uintptr_t data = (uintptr_t)value->data;
60414 uintptr_t oldData = (uintptr_t)oldValue->data;
60415 UA_UInt32 memSize = value->type->memSize;
60416 for(size_t i = 0; i < length; ++i) {
60417 if(detectScalarDeadBand(data1: (const void*)data, data2: (const void*)oldData,
60418 type: value->type, deadband: deadbandValue))
60419 return true;
60420 data += memSize;
60421 oldData += memSize;
60422 }
60423 return false;
60424}
60425
60426static UA_Boolean
60427detectValueChange(UA_Server *server, UA_MonitoredItem *mon,
60428 const UA_DataValue *value) {
60429 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60430
60431 /* Status changes are always reported */
60432 if(value->hasStatus != mon->lastValue.hasStatus ||
60433 value->status != mon->lastValue.status) {
60434 return true;
60435 }
60436
60437 /* Default trigger is Status + Value */
60438 UA_DataChangeTrigger trigger = UA_DATACHANGETRIGGER_STATUSVALUE;
60439
60440 /* Use the configured trigger */
60441 const UA_DataChangeFilter *dcf = NULL;
60442 const UA_ExtensionObject *filter = &mon->parameters.filter;
60443 if(filter->content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) {
60444 dcf = (UA_DataChangeFilter*)filter->content.decoded.data;
60445 trigger = dcf->trigger;
60446 }
60447
60448 /* The status was already tested above */
60449 if(trigger == UA_DATACHANGETRIGGER_STATUS)
60450 return false;
60451
60452 UA_assert(trigger == UA_DATACHANGETRIGGER_STATUSVALUE ||
60453 trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP);
60454
60455 /* Test absolute deadband */
60456 if(dcf && dcf->deadbandType == UA_DEADBANDTYPE_ABSOLUTE &&
60457 value->value.type != NULL && UA_DataType_isNumeric(type: value->value.type))
60458 return detectVariantDeadband(value: &value->value, oldValue: &mon->lastValue.value,
60459 deadbandValue: dcf->deadbandValue);
60460
60461 /* Compare the source timestamp if the trigger requires that */
60462 if(trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP) {
60463 if(value->hasSourceTimestamp != mon->lastValue.hasSourceTimestamp)
60464 return true;
60465 if(value->hasSourceTimestamp &&
60466 value->sourceTimestamp != mon->lastValue.sourceTimestamp)
60467 return true;
60468 }
60469
60470 /* Has the value changed? */
60471 if(value->hasValue != mon->lastValue.hasValue)
60472 return true;
60473 return (UA_order(p1: &value->value, p2: &mon->lastValue.value,
60474 type: &UA_TYPES[UA_TYPES_VARIANT]) != UA_ORDER_EQ);
60475}
60476
60477UA_StatusCode
60478UA_MonitoredItem_createDataChangeNotification(UA_Server *server, UA_Subscription *sub,
60479 UA_MonitoredItem *mon,
60480 const UA_DataValue *value) {
60481 /* Allocate a new notification */
60482 UA_Notification *newNotification = UA_Notification_new();
60483 if(!newNotification)
60484 return UA_STATUSCODE_BADOUTOFMEMORY;
60485
60486 /* Prepare the notification */
60487 newNotification->mon = mon;
60488 newNotification->data.dataChange.clientHandle = mon->parameters.clientHandle;
60489 UA_StatusCode retval = UA_DataValue_copy(src: value, dst: &newNotification->data.dataChange.value);
60490 if(retval != UA_STATUSCODE_GOOD) {
60491 UA_free(ptr: newNotification);
60492 return retval;
60493 }
60494
60495 /* Enqueue the notification */
60496 UA_assert(sub);
60497 UA_Notification_enqueueAndTrigger(server, n: newNotification);
60498 return UA_STATUSCODE_GOOD;
60499}
60500
60501/* Moves the value to the MonitoredItem if successful */
60502UA_StatusCode
60503sampleCallbackWithValue(UA_Server *server, UA_Subscription *sub,
60504 UA_MonitoredItem *mon, UA_DataValue *value) {
60505 UA_assert(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
60506
60507 /* Has the value changed (with the filters applied)? */
60508 UA_Boolean changed = detectValueChange(server, mon, value);
60509 if(!changed) {
60510 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
60511 "MonitoredItem %" PRIi32 " | "
60512 "The value has not changed", mon->monitoredItemId);
60513 UA_DataValue_clear(p: value);
60514 return UA_STATUSCODE_GOOD;
60515 }
60516
60517 /* The MonitoredItem is attached to a subscription (not server-local).
60518 * Prepare a notification and enqueue it. */
60519 if(sub) {
60520 UA_StatusCode retval =
60521 UA_MonitoredItem_createDataChangeNotification(server, sub, mon, value);
60522 if(retval != UA_STATUSCODE_GOOD)
60523 return retval;
60524 }
60525
60526 /* <-- Point of no return --> */
60527
60528 /* Move/store the value for filter comparison and TransferSubscription */
60529 UA_DataValue_clear(p: &mon->lastValue);
60530 mon->lastValue = *value;
60531
60532 /* Call the local callback if the MonitoredItem is not attached to a
60533 * subscription. Do this at the very end. Because the callback might delete
60534 * the subscription. */
60535 if(!sub) {
60536 UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*) mon;
60537 void *nodeContext = NULL;
60538 getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &nodeContext);
60539 UA_UNLOCK(&server->serviceMutex);
60540 localMon->callback.dataChangeCallback(server,
60541 mon->monitoredItemId, localMon->context,
60542 &mon->itemToMonitor.nodeId, nodeContext,
60543 mon->itemToMonitor.attributeId, value);
60544 UA_LOCK(&server->serviceMutex);
60545 }
60546
60547 return UA_STATUSCODE_GOOD;
60548}
60549
60550void
60551UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) {
60552 UA_LOCK(&server->serviceMutex);
60553 monitoredItem_sampleCallback(server, monitoredItem);
60554 UA_UNLOCK(&server->serviceMutex);
60555}
60556
60557void
60558monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) {
60559 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60560
60561 UA_Subscription *sub = monitoredItem->subscription;
60562 UA_Session *session = &server->adminSession;
60563 if(sub)
60564 session = sub->session;
60565
60566 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
60567 "MonitoredItem %" PRIi32 " | "
60568 "Sample callback called", monitoredItem->monitoredItemId);
60569
60570 UA_assert(monitoredItem->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
60571
60572 /* Sample the value. The sample can still point into the node. */
60573 UA_DataValue value = UA_Server_readWithSession(server, session,
60574 item: &monitoredItem->itemToMonitor,
60575 timestampsToReturn: monitoredItem->timestampsToReturn);
60576
60577 /* Operate on the sample. The sample is consumed when the status is good. */
60578 UA_StatusCode res = sampleCallbackWithValue(server, sub, mon: monitoredItem, value: &value);
60579 if(res != UA_STATUSCODE_GOOD) {
60580 UA_DataValue_clear(p: &value);
60581 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
60582 "MonitoredItem %" PRIi32 " | "
60583 "Sampling returned the statuscode %s",
60584 monitoredItem->monitoredItemId,
60585 UA_StatusCode_name(res));
60586 }
60587}
60588
60589#endif /* UA_ENABLE_SUBSCRIPTIONS */
60590
60591/**** amalgamated original file "/src/server/ua_subscription_events.c" ****/
60592
60593/* This Source Code Form is subject to the terms of the Mozilla Public
60594 * License, v. 2.0. If a copy of the MPL was not distributed with this
60595 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
60596 *
60597 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
60598 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
60599 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
60600 */
60601
60602
60603#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
60604
60605/* We use a 16-Byte ByteString as an identifier */
60606UA_StatusCode
60607UA_Event_generateEventId(UA_ByteString *generatedId) {
60608 /* EventId is a ByteString, which is basically just a string
60609 * We will use a 16-Byte ByteString as an identifier */
60610 UA_StatusCode res = UA_ByteString_allocBuffer(bs: generatedId, length: 16 * sizeof(UA_Byte));
60611 if(res != UA_STATUSCODE_GOOD)
60612 return res;
60613 UA_UInt32 *ids = (UA_UInt32*)generatedId->data;
60614 ids[0] = UA_UInt32_random();
60615 ids[1] = UA_UInt32_random();
60616 ids[2] = UA_UInt32_random();
60617 ids[3] = UA_UInt32_random();
60618 return UA_STATUSCODE_GOOD;
60619}
60620
60621UA_StatusCode
60622UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
60623 UA_NodeId *outNodeId) {
60624 UA_LOCK(&server->serviceMutex);
60625 if(!outNodeId) {
60626 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
60627 msg: "outNodeId must not be NULL. The event's NodeId must be returned "
60628 "so it can be triggered.");
60629 UA_UNLOCK(&server->serviceMutex);
60630 return UA_STATUSCODE_BADINVALIDARGUMENT;
60631 }
60632
60633 /* Make sure the eventType is a subtype of BaseEventType */
60634 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
60635 if(!isNodeInTree_singleRef(server, leafNode: &eventType, nodeToFind: &baseEventTypeId,
60636 UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
60637 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
60638 msg: "Event type must be a subtype of BaseEventType!");
60639 UA_UNLOCK(&server->serviceMutex);
60640 return UA_STATUSCODE_BADINVALIDARGUMENT;
60641 }
60642
60643 /* Create an ObjectNode which represents the event */
60644 UA_QualifiedName name;
60645 /* set a dummy name. This is not used. */
60646 name = UA_QUALIFIEDNAME(nsIndex: 0,chars: "E");
60647 UA_NodeId newNodeId = UA_NODEID_NULL;
60648 UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
60649 UA_StatusCode retval = addNode(server, nodeClass: UA_NODECLASS_OBJECT,
60650 requestedNewNodeId: &UA_NODEID_NULL, /* Set a random unused NodeId */
60651 parentNodeId: &UA_NODEID_NULL, /* No parent */
60652 referenceTypeId: &UA_NODEID_NULL, /* No parent reference */
60653 browseName: name, /* an event does not have a name */
60654 typeDefinition: &eventType, /* the type of the event */
60655 attr: (const UA_NodeAttributes*)&oAttr, /* default attributes are fine */
60656 attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
60657 NULL, /* no node context */
60658 outNewNodeId: &newNodeId);
60659 if(retval != UA_STATUSCODE_GOOD) {
60660 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
60661 msg: "Adding event failed. StatusCode %s", UA_StatusCode_name(code: retval));
60662 UA_UNLOCK(&server->serviceMutex);
60663 return retval;
60664 }
60665
60666 /* Find the eventType variable */
60667 name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType");
60668 UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: newNodeId, browsePathSize: 1, browsePath: &name);
60669 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
60670 retval = bpr.statusCode;
60671 UA_BrowsePathResult_clear(p: &bpr);
60672 deleteNode(server, nodeId: newNodeId, true);
60673 UA_NodeId_clear(p: &newNodeId);
60674 UA_UNLOCK(&server->serviceMutex);
60675 return retval;
60676 }
60677
60678 /* Set the EventType */
60679 UA_Variant value;
60680 UA_Variant_init(p: &value);
60681 UA_Variant_setScalar(v: &value, p: (void*)(uintptr_t)&eventType, type: &UA_TYPES[UA_TYPES_NODEID]);
60682 retval = writeValueAttribute(server, session: &server->adminSession,
60683 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
60684 UA_BrowsePathResult_clear(p: &bpr);
60685 if(retval != UA_STATUSCODE_GOOD) {
60686 deleteNode(server, nodeId: newNodeId, true);
60687 UA_NodeId_clear(p: &newNodeId);
60688 UA_UNLOCK(&server->serviceMutex);
60689 return retval;
60690 }
60691
60692 *outNodeId = newNodeId;
60693 UA_UNLOCK(&server->serviceMutex);
60694 return UA_STATUSCODE_GOOD;
60695}
60696
60697static UA_StatusCode
60698eventSetStandardFields(UA_Server *server, const UA_NodeId *event,
60699 const UA_NodeId *origin, UA_ByteString *outEventId) {
60700 /* Set the SourceNode */
60701 UA_StatusCode retval;
60702 UA_QualifiedName name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "SourceNode");
60703 UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name);
60704 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
60705 retval = bpr.statusCode;
60706 UA_BrowsePathResult_clear(p: &bpr);
60707 return retval;
60708 }
60709 UA_Variant value;
60710 UA_Variant_init(p: &value);
60711 UA_Variant_setScalarCopy(v: &value, p: origin, type: &UA_TYPES[UA_TYPES_NODEID]);
60712 retval = writeValueAttribute(server, session: &server->adminSession,
60713 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
60714 UA_Variant_clear(p: &value);
60715 UA_BrowsePathResult_clear(p: &bpr);
60716 if(retval != UA_STATUSCODE_GOOD)
60717 return retval;
60718
60719 /* Set the ReceiveTime */
60720 name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "ReceiveTime");
60721 bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name);
60722 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
60723 retval = bpr.statusCode;
60724 UA_BrowsePathResult_clear(p: &bpr);
60725 return retval;
60726 }
60727 UA_DateTime rcvTime = UA_DateTime_now();
60728 UA_Variant_setScalar(v: &value, p: &rcvTime, type: &UA_TYPES[UA_TYPES_DATETIME]);
60729 retval = writeValueAttribute(server, session: &server->adminSession,
60730 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
60731 UA_BrowsePathResult_clear(p: &bpr);
60732 if(retval != UA_STATUSCODE_GOOD)
60733 return retval;
60734
60735 /* Set the EventId */
60736 UA_ByteString eventId = UA_BYTESTRING_NULL;
60737 retval = UA_Event_generateEventId(generatedId: &eventId);
60738 if(retval != UA_STATUSCODE_GOOD)
60739 return retval;
60740 name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventId");
60741 bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name);
60742 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
60743 retval = bpr.statusCode;
60744 UA_ByteString_clear(p: &eventId);
60745 UA_BrowsePathResult_clear(p: &bpr);
60746 return retval;
60747 }
60748 UA_Variant_init(p: &value);
60749 UA_Variant_setScalar(v: &value, p: &eventId, type: &UA_TYPES[UA_TYPES_BYTESTRING]);
60750 retval = writeValueAttribute(server, session: &server->adminSession,
60751 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
60752 UA_BrowsePathResult_clear(p: &bpr);
60753 if(retval != UA_STATUSCODE_GOOD) {
60754 UA_ByteString_clear(p: &eventId);
60755 return retval;
60756 }
60757
60758 /* Return the EventId */
60759 if(outEventId)
60760 *outEventId = eventId;
60761 else
60762 UA_ByteString_clear(p: &eventId);
60763
60764 return UA_STATUSCODE_GOOD;
60765}
60766
60767/* Filters an event according to the filter specified by mon and then adds it to
60768 * mons notification queue */
60769UA_StatusCode
60770UA_Event_addEventToMonitoredItem(UA_Server *server, const UA_NodeId *event,
60771 UA_MonitoredItem *mon) {
60772 UA_Notification *notification = UA_Notification_new();
60773 if(!notification)
60774 return UA_STATUSCODE_BADOUTOFMEMORY;
60775
60776 if(mon->parameters.filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER])
60777 return UA_STATUSCODE_BADFILTERNOTALLOWED;
60778 UA_EventFilter *eventFilter = (UA_EventFilter*)
60779 mon->parameters.filter.content.decoded.data;
60780
60781 /* The MonitoredItem must be attached to a Subscription. This code path is
60782 * not taken for local MonitoredItems (once they are enabled for Events). */
60783 UA_Subscription *sub = mon->subscription;
60784 UA_assert(sub);
60785
60786 UA_Session *session = sub->session;
60787 UA_StatusCode retval = filterEvent(server, session, eventNode: event,
60788 filter: eventFilter, efl: &notification->data.event,
60789 result: &notification->result);
60790 if(retval != UA_STATUSCODE_GOOD) {
60791 UA_Notification_delete(n: notification);
60792 if(retval == UA_STATUSCODE_BADNOMATCH)
60793 return UA_STATUSCODE_GOOD;
60794 return retval;
60795 }
60796
60797 notification->data.event.clientHandle = mon->parameters.clientHandle;
60798 notification->mon = mon;
60799
60800 UA_Notification_enqueueAndTrigger(server, n: notification);
60801 return UA_STATUSCODE_GOOD;
60802}
60803
60804#ifdef UA_ENABLE_HISTORIZING
60805static void
60806setHistoricalEvent(UA_Server *server, const UA_NodeId *origin,
60807 const UA_NodeId *emitNodeId, const UA_NodeId *eventNodeId) {
60808 UA_Variant historicalEventFilterValue;
60809 UA_Variant_init(p: &historicalEventFilterValue);
60810
60811 /* A HistoricalEventNode that has event history available will provide this property */
60812 UA_StatusCode retval =
60813 readObjectProperty(server, objectId: *emitNodeId,
60814 propertyName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "HistoricalEventFilter"),
60815 value: &historicalEventFilterValue);
60816 if(retval != UA_STATUSCODE_GOOD) {
60817 /* Do not vex users with no match errors */
60818 if(retval != UA_STATUSCODE_BADNOMATCH)
60819 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60820 msg: "Cannot read the HistoricalEventFilter property of a "
60821 "listening node. StatusCode %s",
60822 UA_StatusCode_name(code: retval));
60823 return;
60824 }
60825
60826 /* If found then check if HistoricalEventFilter property has a valid value */
60827 if(UA_Variant_isEmpty(v: &historicalEventFilterValue) ||
60828 !UA_Variant_isScalar(v: &historicalEventFilterValue) ||
60829 historicalEventFilterValue.type != &UA_TYPES[UA_TYPES_EVENTFILTER]) {
60830 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60831 msg: "HistoricalEventFilter property of a listening node "
60832 "does not have a valid value");
60833 UA_Variant_clear(p: &historicalEventFilterValue);
60834 return;
60835 }
60836
60837 /* Finally, if found and valid then filter */
60838 UA_EventFilter *filter = (UA_EventFilter*) historicalEventFilterValue.data;
60839 UA_EventFieldList efl;
60840 UA_EventFilterResult result;
60841 retval = filterEvent(server, session: &server->adminSession,
60842 eventNode: eventNodeId, filter, efl: &efl, result: &result);
60843 if(retval == UA_STATUSCODE_GOOD)
60844 server->config.historyDatabase.setEvent(server, server->config.historyDatabase.context,
60845 origin, emitNodeId, filter, &efl);
60846 UA_EventFilterResult_clear(p: &result);
60847 UA_Variant_clear(p: &historicalEventFilterValue);
60848 UA_EventFieldList_clear(p: &efl);
60849}
60850#endif
60851
60852static const UA_NodeId objectsFolderId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_OBJECTSFOLDER}};
60853#define EMIT_REFS_ROOT_COUNT 4
60854static const UA_NodeId emitReferencesRoots[EMIT_REFS_ROOT_COUNT] =
60855 {{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}},
60856 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}},
60857 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASEVENTSOURCE}},
60858 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASNOTIFIER}}};
60859
60860static const UA_NodeId isInFolderReferences[2] =
60861 {{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}},
60862 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}};
60863
60864UA_StatusCode
60865triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
60866 const UA_NodeId origin, UA_ByteString *outEventId,
60867 const UA_Boolean deleteEventNode) {
60868 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60869
60870 UA_LOG_NODEID_DEBUG(&origin,
60871 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
60872 "Events: An event is triggered on node %.*s",
60873 (int)nodeIdStr.length, nodeIdStr.data));
60874
60875#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
60876 UA_Boolean isCallerAC = false;
60877 if(isConditionOrBranch(server, &eventNodeId, &origin, &isCallerAC)) {
60878 if(!isCallerAC) {
60879 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
60880 "Condition Events: Please use A&C API to trigger Condition Events 0x%08X",
60881 UA_STATUSCODE_BADINVALIDARGUMENT);
60882 return UA_STATUSCODE_BADINVALIDARGUMENT;
60883 }
60884 }
60885#endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
60886
60887 /* Check that the origin node exists */
60888 const UA_Node *originNode = UA_NODESTORE_GET(server, &origin);
60889 if(!originNode) {
60890 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
60891 msg: "Origin node for event does not exist.");
60892 return UA_STATUSCODE_BADNOTFOUND;
60893 }
60894 UA_NODESTORE_RELEASE(server, originNode);
60895
60896 /* Make sure the origin is in the ObjectsFolder (TODO: or in the ViewsFolder) */
60897 /* Only use Organizes and HasComponent to check if we are below the ObjectsFolder */
60898 UA_StatusCode retval;
60899 UA_ReferenceTypeSet refTypes;
60900 UA_ReferenceTypeSet_init(set: &refTypes);
60901 for(int i = 0; i < 2; ++i) {
60902 UA_ReferenceTypeSet tmpRefTypes;
60903 retval = referenceTypeIndices(server, refType: &isInFolderReferences[i], indices: &tmpRefTypes, true);
60904 if(retval != UA_STATUSCODE_GOOD) {
60905 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60906 msg: "Events: Could not create the list of references and their subtypes "
60907 "with StatusCode %s", UA_StatusCode_name(code: retval));
60908 }
60909 refTypes = UA_ReferenceTypeSet_union(setA: refTypes, setB: tmpRefTypes);
60910 }
60911
60912 if(!isNodeInTree(server, leafNode: &origin, nodeToFind: &objectsFolderId, relevantRefs: &refTypes)) {
60913 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
60914 msg: "Node for event must be in ObjectsFolder!");
60915 return UA_STATUSCODE_BADINVALIDARGUMENT;
60916 }
60917
60918 /* Update the standard fields of the event */
60919 retval = eventSetStandardFields(server, event: &eventNodeId, origin: &origin, outEventId);
60920 if(retval != UA_STATUSCODE_GOOD) {
60921 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60922 msg: "Events: Could not set the standard event fields with StatusCode %s",
60923 UA_StatusCode_name(code: retval));
60924 return retval;
60925 }
60926
60927 /* List of nodes that emit the node. Events propagate upwards (bubble up) in
60928 * the node hierarchy. */
60929 UA_ExpandedNodeId *emitNodes = NULL;
60930 size_t emitNodesSize = 0;
60931
60932 /* Add the server node to the list of nodes from which the event is emitted.
60933 * The server node emits all events.
60934 *
60935 * Part 3, 7.17: In particular, the root notifier of a Server, the Server
60936 * Object defined in Part 5, is always capable of supplying all Events from
60937 * a Server and as such has implied HasEventSource References to every event
60938 * source in a Server. */
60939 UA_NodeId emitStartNodes[2];
60940 emitStartNodes[0] = origin;
60941 emitStartNodes[1] = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER);
60942
60943 /* Get all ReferenceTypes over which the events propagate */
60944 UA_ReferenceTypeSet emitRefTypes;
60945 UA_ReferenceTypeSet_init(set: &emitRefTypes);
60946 for(size_t i = 0; i < EMIT_REFS_ROOT_COUNT; i++) {
60947 UA_ReferenceTypeSet tmpRefTypes;
60948 retval = referenceTypeIndices(server, refType: &emitReferencesRoots[i], indices: &tmpRefTypes, true);
60949 if(retval != UA_STATUSCODE_GOOD) {
60950 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60951 msg: "Events: Could not create the list of references for event "
60952 "propagation with StatusCode %s", UA_StatusCode_name(code: retval));
60953 goto cleanup;
60954 }
60955 emitRefTypes = UA_ReferenceTypeSet_union(setA: emitRefTypes, setB: tmpRefTypes);
60956 }
60957
60958 /* Get the list of nodes in the hierarchy that emits the event. */
60959 retval = browseRecursive(server, startNodesSize: 2, startNodes: emitStartNodes, browseDirection: UA_BROWSEDIRECTION_INVERSE,
60960 refTypes: &emitRefTypes, nodeClassMask: UA_NODECLASS_UNSPECIFIED, true,
60961 resultsSize: &emitNodesSize, results: &emitNodes);
60962 if(retval != UA_STATUSCODE_GOOD) {
60963 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60964 msg: "Events: Could not create the list of nodes listening on the "
60965 "event with StatusCode %s", UA_StatusCode_name(code: retval));
60966 goto cleanup;
60967 }
60968
60969 /* Add the event to the listening MonitoredItems at each relevant node */
60970 for(size_t i = 0; i < emitNodesSize; i++) {
60971 /* Get the node */
60972 const UA_Node *node = UA_NODESTORE_GET(server, &emitNodes[i].nodeId);
60973 if(!node)
60974 continue;
60975
60976 /* Only consider objects */
60977 if(node->head.nodeClass != UA_NODECLASS_OBJECT) {
60978 UA_NODESTORE_RELEASE(server, node);
60979 continue;
60980 }
60981
60982 /* Add event to monitoreditems */
60983 UA_MonitoredItem *mon = node->head.monitoredItems;
60984 for(; mon != NULL; mon = mon->sampling.nodeListNext) {
60985 /* Is this an Event-MonitoredItem? */
60986 if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
60987 continue;
60988 retval = UA_Event_addEventToMonitoredItem(server, event: &eventNodeId, mon);
60989 if(retval != UA_STATUSCODE_GOOD) {
60990 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60991 msg: "Events: Could not add the event to a listening "
60992 "node with StatusCode %s", UA_StatusCode_name(code: retval));
60993 retval = UA_STATUSCODE_GOOD; /* Only log problems with individual emit nodes */
60994 }
60995 }
60996
60997 UA_NODESTORE_RELEASE(server, node);
60998
60999 /* Add event entry in the historical database */
61000#ifdef UA_ENABLE_HISTORIZING
61001 if(server->config.historyDatabase.setEvent)
61002 setHistoricalEvent(server, origin: &origin, emitNodeId: &emitNodes[i].nodeId, eventNodeId: &eventNodeId);
61003#endif
61004 }
61005
61006 /* Delete the node representation of the event */
61007 if(deleteEventNode) {
61008 retval = deleteNode(server, nodeId: eventNodeId, true);
61009 if(retval != UA_STATUSCODE_GOOD) {
61010 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
61011 msg: "Attempt to remove event using deleteNode failed. StatusCode %s",
61012 UA_StatusCode_name(code: retval));
61013 }
61014 }
61015
61016 cleanup:
61017 UA_Array_delete(p: emitNodes, size: emitNodesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
61018 return retval;
61019}
61020
61021UA_StatusCode
61022UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
61023 const UA_NodeId origin, UA_ByteString *outEventId,
61024 const UA_Boolean deleteEventNode) {
61025 UA_LOCK(&server->serviceMutex);
61026 UA_StatusCode res =
61027 triggerEvent(server, eventNodeId, origin, outEventId, deleteEventNode);
61028 UA_UNLOCK(&server->serviceMutex);
61029 return res;
61030}
61031#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
61032
61033/**** amalgamated original file "/src/server/ua_subscription_events_filter.c" ****/
61034
61035/* This Source Code Form is subject to the terms of the Mozilla Public
61036 * License, v. 2.0. If a copy of the MPL was not distributed with this
61037 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
61038 *
61039 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
61040 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
61041 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
61042 */
61043
61044
61045#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
61046
61047typedef struct {
61048 UA_Server *server;
61049 UA_Session *session;
61050 const UA_NodeId *eventNode;
61051 const UA_ContentFilter *contentFilter;
61052 UA_ContentFilterResult *contentFilterResult;
61053 UA_Variant *valueResult;
61054 UA_UInt16 index;
61055} UA_FilterOperatorContext;
61056
61057static UA_StatusCode
61058evaluateWhereClauseContentFilter(UA_FilterOperatorContext *ctx);
61059
61060/* Resolves a variant of type string or boolean into a corresponding status code */
61061static UA_StatusCode
61062resolveBoolean(UA_Variant operand) {
61063 UA_String value;
61064 value = UA_STRING(chars: "True");
61065 if(((operand.type == &UA_TYPES[UA_TYPES_STRING]) &&
61066 (UA_String_equal(s1: (UA_String *)operand.data, s2: &value))) ||
61067 ((operand.type == &UA_TYPES[UA_TYPES_BOOLEAN]) &&
61068 (*(UA_Boolean *)operand.data == UA_TRUE))) {
61069 return UA_STATUSCODE_GOOD;
61070 }
61071 value = UA_STRING(chars: "False");
61072 if(((operand.type == &UA_TYPES[UA_TYPES_STRING]) &&
61073 (UA_String_equal(s1: (UA_String *)operand.data, s2: &value))) ||
61074 ((operand.type == &UA_TYPES[UA_TYPES_BOOLEAN]) &&
61075 (*(UA_Boolean *)operand.data == UA_FALSE))) {
61076 return UA_STATUSCODE_BADNOMATCH;
61077 }
61078
61079 /* If the operand can't be resolved, an error is returned */
61080 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61081}
61082
61083/* Part 4: 7.4.4.5 SimpleAttributeOperand
61084 * The clause can point to any attribute of nodes. Either a child of the event
61085 * node and also the event type. */
61086static UA_StatusCode
61087resolveSimpleAttributeOperand(UA_Server *server, UA_Session *session,
61088 const UA_NodeId *origin,
61089 const UA_SimpleAttributeOperand *sao,
61090 UA_Variant *value) {
61091 /* Prepare the ReadValueId */
61092 UA_ReadValueId rvi;
61093 UA_ReadValueId_init(p: &rvi);
61094 rvi.indexRange = sao->indexRange;
61095 rvi.attributeId = sao->attributeId;
61096
61097 UA_DataValue v;
61098
61099 if(sao->browsePathSize == 0) {
61100 /* If this list (browsePath) is empty, the Node is the instance of the
61101 * TypeDefinition. (Part 4, 7.4.4.5) */
61102 rvi.nodeId = *origin;
61103
61104 /* A Condition is an indirection. Look up the target node. */
61105 /* TODO: check for Branches! One Condition could have multiple Branches */
61106 UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_CONDITIONTYPE);
61107 if(UA_NodeId_equal(n1: &sao->typeDefinitionId, n2: &conditionTypeId)) {
61108#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
61109 UA_StatusCode res = UA_getConditionId(server, origin, &rvi.nodeId);
61110 if(res != UA_STATUSCODE_GOOD)
61111 return res;
61112#else
61113 return UA_STATUSCODE_BADNOTSUPPORTED;
61114#endif
61115 }
61116
61117 v = UA_Server_readWithSession(server, session, item: &rvi,
61118 timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER);
61119 } else {
61120 /* Resolve the browse path, starting from the event-source (and not the
61121 * typeDefinitionId). */
61122 UA_BrowsePathResult bpr =
61123 browseSimplifiedBrowsePath(server, origin: *origin,
61124 browsePathSize: sao->browsePathSize, browsePath: sao->browsePath);
61125 if(bpr.targetsSize == 0 && bpr.statusCode == UA_STATUSCODE_GOOD)
61126 bpr.statusCode = UA_STATUSCODE_BADNOTFOUND;
61127 if(bpr.statusCode != UA_STATUSCODE_GOOD) {
61128 UA_StatusCode res = bpr.statusCode;
61129 UA_BrowsePathResult_clear(p: &bpr);
61130 return res;
61131 }
61132
61133 /* Use the first match */
61134 rvi.nodeId = bpr.targets[0].targetId.nodeId;
61135 v = UA_Server_readWithSession(server, session, item: &rvi,
61136 timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER);
61137 UA_BrowsePathResult_clear(p: &bpr);
61138 }
61139
61140 /* Move the result to the output */
61141 if(v.status == UA_STATUSCODE_GOOD && v.hasValue)
61142 *value = v.value;
61143 else
61144 UA_Variant_clear(p: &v.value);
61145 return v.status;
61146}
61147
61148/* Resolve operands to variants according to the operand type.
61149 * Part 4: 7.17.3 Table 142 specifies the allowed types. */
61150static UA_Variant
61151resolveOperand(UA_FilterOperatorContext *ctx, UA_UInt16 nr) {
61152 UA_StatusCode res;
61153 UA_Variant variant;
61154 UA_Variant_init(p: &variant);
61155 UA_ExtensionObject *op = &ctx->contentFilter->elements[ctx->index].filterOperands[nr];
61156 if(op->content.decoded.type == &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]) {
61157 /* SimpleAttributeOperand */
61158 res = resolveSimpleAttributeOperand(server: ctx->server, session: ctx->session, origin: ctx->eventNode,
61159 sao: (UA_SimpleAttributeOperand *)op->content.decoded.data,
61160 value: &variant);
61161 } else if(op->content.decoded.type == &UA_TYPES[UA_TYPES_LITERALOPERAND]) {
61162 /* LiteralOperand */
61163 variant = ((UA_LiteralOperand *)op->content.decoded.data)->value;
61164 res = UA_STATUSCODE_GOOD;
61165 } else if(op->content.decoded.type == &UA_TYPES[UA_TYPES_ELEMENTOPERAND]) {
61166 /* ElementOperand */
61167 UA_UInt16 oldIndex = ctx->index;
61168 ctx->index = (UA_UInt16)((UA_ElementOperand *)op->content.decoded.data)->index;
61169 res = evaluateWhereClauseContentFilter(ctx);
61170 variant = ctx->valueResult[ctx->index];
61171 ctx->index = oldIndex; /* restore the old index */
61172 } else {
61173 res = UA_STATUSCODE_BADFILTEROPERANDINVALID;
61174 }
61175
61176 if(res != UA_STATUSCODE_GOOD && res != UA_STATUSCODE_BADNOMATCH) {
61177 variant.type = NULL;
61178 ctx->contentFilterResult->elementResults[ctx->index].operandStatusCodes[nr] = res;
61179 }
61180
61181 return variant;
61182}
61183
61184static UA_StatusCode
61185ofTypeOperator(UA_FilterOperatorContext *ctx) {
61186 UA_ContentFilterElement *pElement = &ctx->contentFilter->elements[ctx->index];
61187 UA_Boolean result = false;
61188 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61189 if(pElement->filterOperandsSize != 1)
61190 return UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
61191 if(pElement->filterOperands[0].content.decoded.type !=
61192 &UA_TYPES[UA_TYPES_LITERALOPERAND])
61193 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61194
61195 UA_LiteralOperand *literalOperand =
61196 (UA_LiteralOperand *) pElement->filterOperands[0].content.decoded.data;
61197 if(!UA_Variant_isScalar(v: &literalOperand->value))
61198 return UA_STATUSCODE_BADEVENTFILTERINVALID;
61199
61200 if(literalOperand->value.type != &UA_TYPES[UA_TYPES_NODEID] || literalOperand->value.data == NULL)
61201 return UA_STATUSCODE_BADEVENTFILTERINVALID;
61202
61203 UA_NodeId *literalOperandNodeId = (UA_NodeId *) literalOperand->value.data;
61204 UA_Variant typeNodeIdVariant;
61205 UA_Variant_init(p: &typeNodeIdVariant);
61206 UA_StatusCode readStatusCode =
61207 readObjectProperty(server: ctx->server, objectId: *ctx->eventNode,
61208 propertyName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType"), value: &typeNodeIdVariant);
61209 if(readStatusCode != UA_STATUSCODE_GOOD)
61210 return readStatusCode;
61211
61212 if(!UA_Variant_isScalar(v: &typeNodeIdVariant) ||
61213 typeNodeIdVariant.type != &UA_TYPES[UA_TYPES_NODEID] ||
61214 typeNodeIdVariant.data == NULL) {
61215 UA_LOG_ERROR(logger: &ctx->server->config.logger, category: UA_LOGCATEGORY_SERVER,
61216 msg: "EventType has an invalid type.");
61217 UA_Variant_clear(p: &typeNodeIdVariant);
61218 return UA_STATUSCODE_BADINTERNALERROR;
61219 }
61220 /* check if the eventtype-nodeid is equal to the given oftype argument */
61221 result = UA_NodeId_equal(n1: (UA_NodeId*) typeNodeIdVariant.data, n2: literalOperandNodeId);
61222 /* check if the eventtype-nodeid is a subtype of the given oftype argument */
61223 if(!result)
61224 result = isNodeInTree_singleRef(server: ctx->server,
61225 leafNode: (UA_NodeId*) typeNodeIdVariant.data,
61226 nodeToFind: literalOperandNodeId,
61227 UA_REFERENCETYPEINDEX_HASSUBTYPE);
61228 UA_Variant_clear(p: &typeNodeIdVariant);
61229 if(!result)
61230 return UA_STATUSCODE_BADNOMATCH;
61231 return UA_STATUSCODE_GOOD;
61232}
61233
61234static UA_StatusCode
61235andOperator(UA_FilterOperatorContext *ctx) {
61236 UA_StatusCode firstBoolean_and = resolveBoolean(operand: resolveOperand(ctx, nr: 0));
61237 if(firstBoolean_and == UA_STATUSCODE_BADNOMATCH) {
61238 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61239 return UA_STATUSCODE_BADNOMATCH;
61240 }
61241 /* Evaluation of second operand */
61242 UA_StatusCode secondBoolean = resolveBoolean(operand: resolveOperand(ctx, nr: 1));
61243 /* Filteroperator AND */
61244 if(secondBoolean == UA_STATUSCODE_BADNOMATCH) {
61245 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61246 return UA_STATUSCODE_BADNOMATCH;
61247 }
61248 if((firstBoolean_and == UA_STATUSCODE_GOOD) &&
61249 (secondBoolean == UA_STATUSCODE_GOOD)) {
61250 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61251 return UA_STATUSCODE_GOOD;
61252 }
61253 return UA_STATUSCODE_BADFILTERELEMENTINVALID;
61254}
61255
61256static UA_StatusCode
61257orOperator(UA_FilterOperatorContext *ctx) {
61258 UA_StatusCode firstBoolean_or = resolveBoolean(operand: resolveOperand(ctx, nr: 0));
61259 if(firstBoolean_or == UA_STATUSCODE_GOOD) {
61260 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61261 return UA_STATUSCODE_GOOD;
61262 }
61263 /* Evaluation of second operand */
61264 UA_StatusCode secondBoolean = resolveBoolean(operand: resolveOperand(ctx, nr: 1));
61265 if(secondBoolean == UA_STATUSCODE_GOOD) {
61266 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61267 return UA_STATUSCODE_GOOD;
61268 }
61269 if((firstBoolean_or == UA_STATUSCODE_BADNOMATCH) &&
61270 (secondBoolean == UA_STATUSCODE_BADNOMATCH)) {
61271 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61272 return UA_STATUSCODE_BADNOMATCH;
61273 }
61274 return UA_STATUSCODE_BADFILTERELEMENTINVALID;
61275}
61276
61277static UA_Boolean
61278isNumericUnsigned(UA_UInt32 dataTypeKind){
61279 if(dataTypeKind == UA_DATATYPEKIND_UINT64 ||
61280 dataTypeKind == UA_DATATYPEKIND_UINT32 ||
61281 dataTypeKind == UA_DATATYPEKIND_UINT16 ||
61282 dataTypeKind == UA_DATATYPEKIND_BYTE)
61283 return true;
61284 return false;
61285}
61286
61287static UA_Boolean
61288isNumericSigned(UA_UInt32 dataTypeKind){
61289 if(dataTypeKind == UA_DATATYPEKIND_INT64 ||
61290 dataTypeKind == UA_DATATYPEKIND_INT32 ||
61291 dataTypeKind == UA_DATATYPEKIND_INT16 ||
61292 dataTypeKind == UA_DATATYPEKIND_SBYTE)
61293 return true;
61294 return false;
61295}
61296
61297static UA_Boolean
61298isFloatingPoint(UA_UInt32 dataTypeKind){
61299 if(dataTypeKind == UA_DATATYPEKIND_FLOAT ||
61300 dataTypeKind == UA_DATATYPEKIND_DOUBLE)
61301 return true;
61302 return false;
61303}
61304
61305static UA_Boolean
61306isStringType(UA_UInt32 dataTypeKind){
61307 if(dataTypeKind == UA_DATATYPEKIND_STRING ||
61308 dataTypeKind == UA_DATATYPEKIND_BYTESTRING)
61309 return true;
61310 return false;
61311}
61312
61313static UA_StatusCode
61314implicitNumericVariantTransformation(UA_Variant *variant, void *data){
61315 if(variant->type == &UA_TYPES[UA_TYPES_UINT64]){
61316 *(UA_UInt64 *)data = *(UA_UInt64 *)variant->data;
61317 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61318 } else if(variant->type == &UA_TYPES[UA_TYPES_UINT32]){
61319 *(UA_UInt64 *)data = *(UA_UInt32 *)variant->data;
61320 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61321 } else if(variant->type == &UA_TYPES[UA_TYPES_UINT16]){
61322 *(UA_UInt64 *)data = *(UA_UInt16 *)variant->data;
61323 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61324 } else if(variant->type == &UA_TYPES[UA_TYPES_BYTE]){
61325 *(UA_UInt64 *)data = *(UA_Byte *)variant->data;
61326 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61327 } else if(variant->type == &UA_TYPES[UA_TYPES_INT64]){
61328 *(UA_Int64 *)data = *(UA_Int64 *)variant->data;
61329 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61330 } else if(variant->type == &UA_TYPES[UA_TYPES_INT32]){
61331 *(UA_Int64 *)data = *(UA_Int32 *)variant->data;
61332 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61333 } else if(variant->type == &UA_TYPES[UA_TYPES_INT16]){
61334 *(UA_Int64 *)data = *(UA_Int16 *)variant->data;
61335 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61336 } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
61337 *(UA_Int64 *)data = *(UA_SByte *)variant->data;
61338 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61339 } else if(variant->type == &UA_TYPES[UA_TYPES_DOUBLE]){
61340 *(UA_Double *)data = *(UA_Double *)variant->data;
61341 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_DOUBLE]);
61342 } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
61343 *(UA_Double *)data = *(UA_Float *)variant->data;
61344 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_DOUBLE]);
61345 } else {
61346 return UA_STATUSCODE_BADTYPEMISMATCH;
61347 }
61348 return UA_STATUSCODE_GOOD;
61349}
61350
61351static UA_StatusCode
61352implicitNumericVariantTransformationUnsingedToSigned(UA_Variant *variant, void *data){
61353 if(variant->type == &UA_TYPES[UA_TYPES_UINT64]){
61354 if(*(UA_UInt64 *)variant->data > UA_INT64_MAX)
61355 return UA_STATUSCODE_BADTYPEMISMATCH;
61356 *(UA_Int64 *)data = *(UA_Int64 *)variant->data;
61357 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61358 } else if(variant->type == &UA_TYPES[UA_TYPES_UINT32]){
61359 *(UA_Int64 *)data = *(UA_Int32 *)variant->data;
61360 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61361 } else if(variant->type == &UA_TYPES[UA_TYPES_UINT16]){
61362 *(UA_Int64 *)data = *(UA_Int16 *)variant->data;
61363 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61364 } else if(variant->type == &UA_TYPES[UA_TYPES_BYTE]){
61365 *(UA_Int64 *)data = *(UA_Byte *)variant->data;
61366 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61367 } else {
61368 return UA_STATUSCODE_BADTYPEMISMATCH;
61369 }
61370 return UA_STATUSCODE_GOOD;
61371}
61372
61373static UA_StatusCode
61374implicitNumericVariantTransformationSignedToUnSigned(UA_Variant *variant, void *data){
61375 if(*(UA_Int64 *)variant->data < 0)
61376 return UA_STATUSCODE_BADTYPEMISMATCH;
61377 if(variant->type == &UA_TYPES[UA_TYPES_INT64]){
61378 *(UA_UInt64 *)data = *(UA_UInt64 *)variant->data;
61379 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61380 } else if(variant->type == &UA_TYPES[UA_TYPES_INT32]){
61381 *(UA_UInt64 *)data = *(UA_UInt32 *)variant->data;
61382 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61383 } else if(variant->type == &UA_TYPES[UA_TYPES_INT16]){
61384 *(UA_UInt64 *)data = *(UA_UInt16 *)variant->data;
61385 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61386 } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
61387 *(UA_UInt64 *)data = *(UA_Byte *)variant->data;
61388 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61389 } else {
61390 return UA_STATUSCODE_BADTYPEMISMATCH;
61391 }
61392 return UA_STATUSCODE_GOOD;
61393}
61394
61395/* 0 -> Same Type, 1 -> Implicit Cast, 2 -> Only explicit Cast, -1 -> cast invalid */
61396static UA_SByte convertLookup[21][21] = {
61397 { 0, 1,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 1,-1, 2,-1,-1, 1, 1, 1,-1},
61398 { 2, 0,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 1,-1, 2,-1,-1, 1, 1, 1,-1},
61399 {-1,-1, 0,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
61400 {-1,-1,-1, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1},
61401 { 2, 2,-1,-1, 0,-1, 2,-1, 2, 2, 2,-1, 2,-1, 2,-1,-1, 2, 2, 2,-1},
61402 {-1,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1, 2,-1,-1, 1,-1,-1,-1,-1,-1,-1},
61403 { 2, 2,-1,-1, 1,-1, 0,-1, 2, 2, 2,-1, 2,-1, 2,-1,-1, 2, 2, 2,-1},
61404 {-1,-1, 2,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1},
61405 { 2, 2,-1,-1, 1,-1, 1,-1, 0, 1, 1,-1, 2,-1, 2,-1,-1, 2, 1, 1,-1},
61406 { 2, 2,-1,-1, 1,-1, 1,-1, 2, 0, 1,-1, 2, 2, 2,-1,-1, 2, 2, 1,-1},
61407 { 2, 2,-1,-1, 1,-1, 1,-1, 2, 2, 0,-1, 2, 2, 2,-1,-1, 2, 2, 2,-1},
61408 {-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1, 0,-1,-1, 1,-1,-1,-1,-1,-1,-1},
61409 { 2, 2,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 0,-1, 2,-1,-1, 1, 1, 1,-1},
61410 {-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1, 0,-1,-1,-1, 2, 1, 1,-1},
61411 { 1, 1,-1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1,-1, 0, 2, 2, 1, 1, 1,-1},
61412 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 0,-1,-1,-1,-1,-1},
61413 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1, 0,-1,-1,-1,-1},
61414 { 2, 2,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 2, 1, 2,-1,-1, 0, 1, 1,-1},
61415 { 2, 2,-1,-1, 1,-1, 1,-1, 2, 1, 1,-1, 2, 2, 2,-1,-1, 2, 0, 1,-1},
61416 { 2, 2,-1,-1, 1,-1, 1,-1, 2, 2, 1,-1, 2, 2, 2,-1,-1, 2, 2, 0,-1},
61417 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0}
61418};
61419
61420/* This array maps the index of the
61421 * standard DataType-Kind order to the
61422 * order of the type convertion array */
61423static UA_Byte dataTypeKindIndex[30] = {
61424 0, 12, 1, 8, 17,
61425 9, 18, 10, 19, 6,
61426 4, 14, 3, 7, 2,
61427 20, 11, 5, 13, 16,
61428 15, 255,255,255,255,
61429 255,255,255,255,255
61430};
61431
61432/* The OPC UA Standard defines in Part 4 several data type casting-rules. (see
61433 * 1.04 part 4 Table 122)
61434 * Return:
61435 * 0 -> same type
61436 * 1 -> types can be casted implicit
61437 * 2 -> types can only be explicitly casted
61438 * -1 -> types can't be casted */
61439static UA_SByte
61440checkTypeCastingOption(const UA_DataType *cast_target, const UA_DataType *cast_source) {
61441 UA_Byte firstOperatorTypeKindIndex = dataTypeKindIndex[cast_target->typeKind];
61442 UA_Byte secondOperatorTypeKindIndex = dataTypeKindIndex[cast_source->typeKind];
61443 if(firstOperatorTypeKindIndex == UA_BYTE_MAX ||
61444 secondOperatorTypeKindIndex == UA_BYTE_MAX)
61445 return -1;
61446
61447 return convertLookup[firstOperatorTypeKindIndex][secondOperatorTypeKindIndex];
61448}
61449
61450/* Compare operation for equal, gt, le, gte, lee
61451 * UA_STATUSCODE_GOOD if the comparison was true
61452 * UA_STATUSCODE_BADNOMATCH if the comparison was false
61453 * UA_STATUSCODE_BADFILTEROPERATORINVALID for invalid operators
61454 * UA_STATUSCODE_BADTYPEMISMATCH if one of the operands was not numeric
61455 * ToDo Array-Casting
61456 */
61457static UA_StatusCode
61458compareOperation(UA_Variant *firstOperand, UA_Variant *secondOperand, UA_FilterOperator op) {
61459 /* get precedence of the operand types */
61460 UA_Int16 firstOperand_precedence = UA_DataType_getPrecedence(type: firstOperand->type);
61461 UA_Int16 secondOperand_precedence = UA_DataType_getPrecedence(type: secondOperand->type);
61462 /* if the types are not equal and one of the precedence-ranks is -1, then there is
61463 no implicit conversion possible and therefore no compare */
61464 if(!UA_NodeId_equal(n1: &firstOperand->type->typeId, n2: &secondOperand->type->typeId) &&
61465 (firstOperand_precedence == -1 || secondOperand_precedence == -1)){
61466 return UA_STATUSCODE_BADTYPEMISMATCH;
61467 }
61468 /* check if the precedence order of the operators is swapped */
61469 UA_Variant *firstCompareOperand = firstOperand;
61470 UA_Variant *secondCompareOperand = secondOperand;
61471 UA_Boolean swapped = false;
61472 if (firstOperand_precedence < secondOperand_precedence){
61473 firstCompareOperand = secondOperand;
61474 secondCompareOperand = firstOperand;
61475 swapped = true;
61476 }
61477 UA_SByte castRule =
61478 checkTypeCastingOption(cast_target: firstCompareOperand->type, cast_source: secondCompareOperand->type);
61479
61480 if(!(castRule == 0 || castRule == 1)){
61481 return UA_STATUSCODE_BADTYPEMISMATCH;
61482 }
61483
61484 /* The operand Data-Types influence the behavior and steps for the comparison.
61485 * We need to check the operand types and store a rule which is used to select
61486 * the right behavior afterwards. */
61487 enum compareHandlingRuleEnum {
61488 UA_TYPES_EQUAL_ORDERED,
61489 UA_TYPES_EQUAL_UNORDERED,
61490 UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED,
61491 UA_TYPES_DIFFERENT_NUMERIC_SIGNED,
61492 UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT,
61493 UA_TYPES_DIFFERENT_TEXT,
61494 UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN,
61495 UA_TYPES_DIFFERENT_COMPARE_EXPLIC,
61496 UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED,
61497 UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED
61498 } compareHandlingRuleEnum;
61499
61500 if(castRule == 0 &&
61501 (UA_DataType_isNumeric(type: firstOperand->type) ||
61502 firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_DATETIME ||
61503 firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_STRING ||
61504 firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_BYTESTRING)){
61505 /* Data-Types with a natural order (allow le, gt, lee, gte) */
61506 compareHandlingRuleEnum = UA_TYPES_EQUAL_ORDERED;
61507 } else if(castRule == 0){
61508 /* Data-Types without a natural order (le, gt, lee, gte are not allowed) */
61509 compareHandlingRuleEnum = UA_TYPES_EQUAL_UNORDERED;
61510 } else if(castRule == 1 &&
61511 isNumericSigned(dataTypeKind: firstOperand->type->typeKind) &&
61512 isNumericSigned(dataTypeKind: secondOperand->type->typeKind)){
61513 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_SIGNED;
61514 } else if(castRule == 1 &&
61515 isNumericUnsigned(dataTypeKind: firstOperand->type->typeKind) &&
61516 isNumericUnsigned(dataTypeKind: secondOperand->type->typeKind)){
61517 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED;
61518 } else if(castRule == 1 &&
61519 isFloatingPoint(dataTypeKind: firstOperand->type->typeKind) &&
61520 isFloatingPoint(dataTypeKind: secondOperand->type->typeKind)){
61521 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT;
61522 } else if(castRule == 1 &&
61523 isStringType(dataTypeKind: firstOperand->type->typeKind)&&
61524 isStringType(dataTypeKind: secondOperand->type->typeKind)){
61525 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_TEXT;
61526 } else if(castRule == 1 &&
61527 isNumericSigned(dataTypeKind: firstOperand->type->typeKind) &&
61528 isNumericUnsigned(dataTypeKind: secondOperand->type->typeKind)){
61529 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED;
61530 } else if(castRule == 1 &&
61531 isNumericSigned(dataTypeKind: secondOperand->type->typeKind) &&
61532 isNumericUnsigned(dataTypeKind: firstOperand->type->typeKind)){
61533 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED;
61534 } else if(castRule == -1 || castRule == 2){
61535 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_COMPARE_EXPLIC;
61536 } else {
61537 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN;
61538 }
61539
61540 if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN)
61541 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61542
61543 if(swapped){
61544 firstCompareOperand = secondCompareOperand;
61545 secondCompareOperand = firstCompareOperand;
61546 }
61547
61548 if(op == UA_FILTEROPERATOR_EQUALS){
61549 UA_Byte variantContent[16];
61550 memset(s: &variantContent, c: 0, n: sizeof(UA_Byte) * 16);
61551 if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_SIGNED ||
61552 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED ||
61553 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT) {
61554 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61555 implicitNumericVariantTransformation(variant: secondCompareOperand, data: &variantContent[8]);
61556 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED) {
61557 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61558 implicitNumericVariantTransformationUnsingedToSigned(variant: secondCompareOperand, data: &variantContent[8]);
61559 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED) {
61560 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61561 implicitNumericVariantTransformationSignedToUnSigned(variant: secondCompareOperand, data: &variantContent[8]);
61562 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_TEXT) {
61563 firstCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
61564 secondCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
61565 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN ||
61566 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_EXPLIC ){
61567 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61568 }
61569 if(UA_order(p1: firstCompareOperand, p2: secondCompareOperand, type: &UA_TYPES[UA_TYPES_VARIANT]) == UA_ORDER_EQ) {
61570 return UA_STATUSCODE_GOOD;
61571 }
61572 } else {
61573 UA_Byte variantContent[16];
61574 memset(s: &variantContent, c: 0, n: sizeof(UA_Byte) * 16);
61575 if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_SIGNED ||
61576 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED ||
61577 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT) {
61578 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61579 implicitNumericVariantTransformation(variant: secondCompareOperand, data: &variantContent[8]);
61580 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED) {
61581 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61582 implicitNumericVariantTransformationUnsingedToSigned(variant: secondCompareOperand, data: &variantContent[8]);
61583 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED) {
61584 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61585 implicitNumericVariantTransformationSignedToUnSigned(variant: secondCompareOperand, data: &variantContent[8]);
61586 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_TEXT) {
61587 firstCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
61588 secondCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
61589 } else if(compareHandlingRuleEnum == UA_TYPES_EQUAL_UNORDERED) {
61590 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61591 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN ||
61592 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_EXPLIC) {
61593 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61594 }
61595 UA_Order gte_result = UA_order(p1: firstCompareOperand, p2: secondCompareOperand,
61596 type: &UA_TYPES[UA_TYPES_VARIANT]);
61597 if(op == UA_FILTEROPERATOR_LESSTHAN) {
61598 if(gte_result == UA_ORDER_LESS) {
61599 return UA_STATUSCODE_GOOD;
61600 }
61601 } else if(op == UA_FILTEROPERATOR_GREATERTHAN) {
61602 if(gte_result == UA_ORDER_MORE) {
61603 return UA_STATUSCODE_GOOD;
61604 }
61605 } else if(op == UA_FILTEROPERATOR_LESSTHANOREQUAL) {
61606 if(gte_result == UA_ORDER_LESS || gte_result == UA_ORDER_EQ) {
61607 return UA_STATUSCODE_GOOD;
61608 }
61609 } else if(op == UA_FILTEROPERATOR_GREATERTHANOREQUAL) {
61610 if(gte_result == UA_ORDER_MORE || gte_result == UA_ORDER_EQ) {
61611 return UA_STATUSCODE_GOOD;
61612 }
61613 }
61614 }
61615 return UA_STATUSCODE_BADNOMATCH;
61616}
61617
61618static UA_StatusCode
61619compareOperator(UA_FilterOperatorContext *ctx) {
61620 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61621 UA_Variant firstOperand = resolveOperand(ctx, nr: 0);
61622 if(UA_Variant_isEmpty(v: &firstOperand))
61623 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61624 UA_Variant secondOperand = resolveOperand(ctx, nr: 1);
61625 if(UA_Variant_isEmpty(v: &secondOperand)) {
61626 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61627 }
61628 /* ToDo remove the following restriction: Add support for arrays */
61629 if(!UA_Variant_isScalar(v: &firstOperand) || !UA_Variant_isScalar(v: &secondOperand)){
61630 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61631 }
61632 return compareOperation(firstOperand: &firstOperand, secondOperand: &secondOperand,
61633 op: ctx->contentFilter->elements[ctx->index].filterOperator);
61634}
61635
61636static UA_StatusCode
61637bitwiseOperator(UA_FilterOperatorContext *ctx) {
61638 /* The bitwise operators all have 2 operands which are evaluated equally. */
61639 UA_Variant firstOperand = resolveOperand(ctx, nr: 0);
61640 if(UA_Variant_isEmpty(v: &firstOperand)) {
61641 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61642 }
61643 UA_Variant secondOperand = resolveOperand(ctx, nr: 1);
61644 if(UA_Variant_isEmpty(v: &secondOperand)) {
61645 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61646 }
61647
61648 UA_Boolean bitwiseAnd =
61649 ctx->contentFilter->elements[ctx->index].filterOperator == UA_FILTEROPERATOR_BITWISEAND;
61650
61651 /* check if the operators are integers */
61652 if(!UA_DataType_isNumeric(type: firstOperand.type) ||
61653 !UA_DataType_isNumeric(type: secondOperand.type) ||
61654 !UA_Variant_isScalar(v: &firstOperand) ||
61655 !UA_Variant_isScalar(v: &secondOperand) ||
61656 (firstOperand.type == &UA_TYPES[UA_TYPES_DOUBLE]) ||
61657 (secondOperand.type == &UA_TYPES[UA_TYPES_DOUBLE]) ||
61658 (secondOperand.type == &UA_TYPES[UA_TYPES_FLOAT]) ||
61659 (firstOperand.type == &UA_TYPES[UA_TYPES_FLOAT])) {
61660 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61661 }
61662
61663 /* check which is the return type (higher precedence == bigger integer)*/
61664 UA_Int16 precedence = UA_DataType_getPrecedence(type: firstOperand.type);
61665 if(precedence > UA_DataType_getPrecedence(type: secondOperand.type)) {
61666 precedence = UA_DataType_getPrecedence(type: secondOperand.type);
61667 }
61668
61669 switch(precedence){
61670 case 3:
61671 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT64];
61672 UA_Int64 result_int64;
61673 if(bitwiseAnd) {
61674 result_int64 = *((UA_Int64 *)firstOperand.data) & *((UA_Int64 *)secondOperand.data);
61675 } else {
61676 result_int64 = *((UA_Int64 *)firstOperand.data) | *((UA_Int64 *)secondOperand.data);
61677 }
61678 UA_Int64_copy(src: &result_int64, dst: (UA_Int64 *) ctx->valueResult[ctx->index].data);
61679 break;
61680 case 4:
61681 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT64];
61682 UA_UInt64 result_uint64s;
61683 if(bitwiseAnd) {
61684 result_uint64s = *((UA_UInt64 *)firstOperand.data) & *((UA_UInt64 *)secondOperand.data);
61685 } else {
61686 result_uint64s = *((UA_UInt64 *)firstOperand.data) | *((UA_UInt64 *)secondOperand.data);
61687 }
61688 UA_UInt64_copy(src: &result_uint64s, dst: (UA_UInt64 *) ctx->valueResult[ctx->index].data);
61689 break;
61690 case 5:
61691 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT32];
61692 UA_Int32 result_int32;
61693 if(bitwiseAnd) {
61694 result_int32 = *((UA_Int32 *)firstOperand.data) & *((UA_Int32 *)secondOperand.data);
61695 } else {
61696 result_int32 = *((UA_Int32 *)firstOperand.data) | *((UA_Int32 *)secondOperand.data);
61697 }
61698 UA_Int32_copy(src: &result_int32, dst: (UA_Int32 *) ctx->valueResult[ctx->index].data);
61699 break;
61700 case 6:
61701 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT32];
61702 UA_UInt32 result_uint32;
61703 if(bitwiseAnd) {
61704 result_uint32 = *((UA_UInt32 *)firstOperand.data) & *((UA_UInt32 *)secondOperand.data);
61705 } else {
61706 result_uint32 = *((UA_UInt32 *)firstOperand.data) | *((UA_UInt32 *)secondOperand.data);
61707 }
61708 UA_UInt32_copy(src: &result_uint32, dst: (UA_UInt32 *) ctx->valueResult[ctx->index].data);
61709 break;
61710 case 8:
61711 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT16];
61712 UA_Int16 result_int16;
61713 if(bitwiseAnd) {
61714 result_int16 = *((UA_Int16 *)firstOperand.data) & *((UA_Int16 *)secondOperand.data);
61715 } else {
61716 result_int16 = *((UA_Int16 *)firstOperand.data) | *((UA_Int16 *)secondOperand.data);
61717 }
61718 UA_Int16_copy(src: &result_int16, dst: (UA_Int16 *) ctx->valueResult[ctx->index].data);
61719 break;
61720 case 9:
61721 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT16];
61722 UA_UInt16 result_uint16;
61723 if(bitwiseAnd) {
61724 result_uint16 = *((UA_UInt16 *)firstOperand.data) & *((UA_UInt16 *)secondOperand.data);
61725 } else {
61726 result_uint16 = *((UA_UInt16 *)firstOperand.data) | *((UA_UInt16 *)secondOperand.data);
61727 }
61728 UA_UInt16_copy(src: &result_uint16, dst: (UA_UInt16 *) ctx->valueResult[ctx->index].data);
61729 break;
61730 case 10:
61731 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_SBYTE];
61732 UA_SByte result_sbyte;
61733 if(bitwiseAnd) {
61734 result_sbyte = *((UA_SByte *)firstOperand.data) & *((UA_SByte *)secondOperand.data);
61735 } else {
61736 result_sbyte = *((UA_SByte *)firstOperand.data) | *((UA_SByte *)secondOperand.data);
61737 }
61738 UA_SByte_copy(src: &result_sbyte, dst: (UA_SByte *) ctx->valueResult[ctx->index].data);
61739 break;
61740 case 11:
61741 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BYTE];
61742 UA_Byte result_byte;
61743 if(bitwiseAnd) {
61744 result_byte = *((UA_Byte *)firstOperand.data) & *((UA_Byte *)secondOperand.data);
61745 } else {
61746 result_byte = *((UA_Byte *)firstOperand.data) | *((UA_Byte *)secondOperand.data);
61747 }
61748 UA_Byte_copy(src: &result_byte, dst: (UA_Byte *) ctx->valueResult[ctx->index].data);
61749 break;
61750 default:
61751 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61752 }
61753 return UA_STATUSCODE_GOOD;
61754}
61755
61756static UA_StatusCode
61757betweenOperator(UA_FilterOperatorContext *ctx) {
61758 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61759
61760 UA_Variant firstOperand = resolveOperand(ctx, nr: 0);
61761 UA_Variant secondOperand = resolveOperand(ctx, nr: 1);
61762 UA_Variant thirdOperand = resolveOperand(ctx, nr: 2);
61763
61764 if((UA_Variant_isEmpty(v: &firstOperand) ||
61765 UA_Variant_isEmpty(v: &secondOperand) ||
61766 UA_Variant_isEmpty(v: &thirdOperand)) ||
61767 (!UA_DataType_isNumeric(type: firstOperand.type) ||
61768 !UA_DataType_isNumeric(type: secondOperand.type) ||
61769 !UA_DataType_isNumeric(type: thirdOperand.type)) ||
61770 (!UA_Variant_isScalar(v: &firstOperand) ||
61771 !UA_Variant_isScalar(v: &secondOperand) ||
61772 !UA_Variant_isScalar(v: &thirdOperand))) {
61773 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61774 }
61775
61776 /* Between can be evaluated through greaterThanOrEqual and lessThanOrEqual */
61777 if(compareOperation(firstOperand: &firstOperand, secondOperand: &secondOperand, op: UA_FILTEROPERATOR_GREATERTHANOREQUAL) == UA_STATUSCODE_GOOD &&
61778 compareOperation(firstOperand: &firstOperand, secondOperand: &thirdOperand, op: UA_FILTEROPERATOR_LESSTHANOREQUAL) == UA_STATUSCODE_GOOD){
61779 return UA_STATUSCODE_GOOD;
61780 }
61781 return UA_STATUSCODE_BADNOMATCH;
61782}
61783
61784static UA_StatusCode
61785inListOperator(UA_FilterOperatorContext *ctx) {
61786 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61787 UA_Variant firstOperand = resolveOperand(ctx, nr: 0);
61788
61789 if(UA_Variant_isEmpty(v: &firstOperand) ||
61790 !UA_Variant_isScalar(v: &firstOperand)) {
61791 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61792 }
61793
61794 /* Evaluating the list of operands */
61795 for(size_t i = 1; i < ctx->contentFilter->elements[ctx->index].filterOperandsSize; i++) {
61796 /* Resolving the current operand */
61797 UA_Variant currentOperator = resolveOperand(ctx, nr: (UA_UInt16)i);
61798
61799 /* Check if the operand conforms to the operator*/
61800 if(UA_Variant_isEmpty(v: &currentOperator) ||
61801 !UA_Variant_isScalar(v: &currentOperator)) {
61802 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61803 }
61804 if(compareOperation(firstOperand: &firstOperand, secondOperand: &currentOperator, op: UA_FILTEROPERATOR_EQUALS)) {
61805 return UA_STATUSCODE_GOOD;
61806 }
61807 }
61808 return UA_STATUSCODE_BADNOMATCH;
61809}
61810
61811static UA_StatusCode
61812isNullOperator(UA_FilterOperatorContext *ctx) {
61813 /* Checking if operand is NULL. This is done by reducing the operand to a
61814 * variant and then checking if it is empty. */
61815 UA_Variant operand = resolveOperand(ctx, nr: 0);
61816 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61817 if(!UA_Variant_isEmpty(v: &operand))
61818 return UA_STATUSCODE_BADNOMATCH;
61819 return UA_STATUSCODE_GOOD;
61820}
61821
61822static UA_StatusCode
61823notOperator(UA_FilterOperatorContext *ctx) {
61824 /* Inverting the boolean value of the operand. */
61825 UA_StatusCode res = resolveBoolean(operand: resolveOperand(ctx, nr: 0));
61826 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61827 /* invert result */
61828 if(res == UA_STATUSCODE_GOOD)
61829 return UA_STATUSCODE_BADNOMATCH;
61830 return UA_STATUSCODE_GOOD;
61831}
61832
61833static UA_StatusCode
61834evaluateWhereClauseContentFilter(UA_FilterOperatorContext *ctx) {
61835 UA_LOCK_ASSERT(&ctx->server->serviceMutex, 1);
61836
61837 if(ctx->contentFilter->elements == NULL || ctx->contentFilter->elementsSize == 0) {
61838 /* Nothing to do.*/
61839 return UA_STATUSCODE_GOOD;
61840 }
61841
61842 /* The first element needs to be evaluated, this might be linked to other
61843 * elements, which are evaluated in these cases. See 7.4.1 in Part 4. */
61844 UA_ContentFilterElement *pElement = &ctx->contentFilter->elements[ctx->index];
61845 UA_StatusCode *result = &ctx->contentFilterResult->elementResults[ctx->index].statusCode;
61846 switch(pElement->filterOperator) {
61847 case UA_FILTEROPERATOR_INVIEW:
61848 /* Fallthrough */
61849 case UA_FILTEROPERATOR_RELATEDTO:
61850 /* Not allowed for event WhereClause according to 7.17.3 in Part 4 */
61851 return UA_STATUSCODE_BADEVENTFILTERINVALID;
61852 case UA_FILTEROPERATOR_EQUALS:
61853 /* Fallthrough */
61854 case UA_FILTEROPERATOR_GREATERTHAN:
61855 /* Fallthrough */
61856 case UA_FILTEROPERATOR_LESSTHAN:
61857 /* Fallthrough */
61858 case UA_FILTEROPERATOR_GREATERTHANOREQUAL:
61859 /* Fallthrough */
61860 case UA_FILTEROPERATOR_LESSTHANOREQUAL:
61861 *result = compareOperator(ctx);
61862 break;
61863 case UA_FILTEROPERATOR_LIKE:
61864 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61865 case UA_FILTEROPERATOR_NOT:
61866 *result = notOperator(ctx);
61867 break;
61868 case UA_FILTEROPERATOR_BETWEEN:
61869 *result = betweenOperator(ctx);
61870 break;
61871 case UA_FILTEROPERATOR_INLIST:
61872 /* ToDo currently only numeric types are allowed */
61873 *result = inListOperator(ctx);
61874 break;
61875 case UA_FILTEROPERATOR_ISNULL:
61876 *result = isNullOperator(ctx);
61877 break;
61878 case UA_FILTEROPERATOR_AND:
61879 *result = andOperator(ctx);
61880 break;
61881 case UA_FILTEROPERATOR_OR:
61882 *result = orOperator(ctx);
61883 break;
61884 case UA_FILTEROPERATOR_CAST:
61885 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61886 case UA_FILTEROPERATOR_BITWISEAND:
61887 *result = bitwiseOperator(ctx);
61888 break;
61889 case UA_FILTEROPERATOR_BITWISEOR:
61890 *result = bitwiseOperator(ctx);
61891 break;
61892 case UA_FILTEROPERATOR_OFTYPE:
61893 *result = ofTypeOperator(ctx);
61894 break;
61895 default:
61896 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61897 }
61898
61899 if(ctx->valueResult[ctx->index].type == &UA_TYPES[UA_TYPES_BOOLEAN]) {
61900 UA_Boolean *res = UA_Boolean_new();
61901 if(ctx->contentFilterResult->elementResults[ctx->index].statusCode == UA_STATUSCODE_GOOD)
61902 *res = true;
61903 else
61904 *res = false;
61905 ctx->valueResult[ctx->index].data = res;
61906 }
61907 return ctx->contentFilterResult->elementResults[ctx->index].statusCode;
61908}
61909
61910/* Exposes the filters For unit tests */
61911UA_StatusCode
61912UA_Server_evaluateWhereClauseContentFilter(UA_Server *server, UA_Session *session,
61913 const UA_NodeId *eventNode,
61914 const UA_ContentFilter *contentFilter,
61915 UA_ContentFilterResult *contentFilterResult) {
61916 if(contentFilter->elementsSize == 0)
61917 return UA_STATUSCODE_GOOD;
61918 /* TODO add maximum lenth size to the server config */
61919 if(contentFilter->elementsSize > 256)
61920 return UA_STATUSCODE_BADINVALIDARGUMENT;
61921 UA_Variant valueResult[256];
61922 for(size_t i = 0; i < contentFilter->elementsSize; ++i) {
61923 UA_Variant_init(p: &valueResult[i]);
61924 }
61925
61926 UA_FilterOperatorContext ctx;
61927 ctx.server = server;
61928 ctx.session = session;
61929 ctx.eventNode = eventNode;
61930 ctx.contentFilter = contentFilter;
61931 ctx.contentFilterResult = contentFilterResult;
61932 ctx.valueResult = valueResult;
61933 ctx.index = 0;
61934
61935 UA_StatusCode res = evaluateWhereClauseContentFilter(ctx: &ctx);
61936 for(size_t i = 0; i < ctx.contentFilter->elementsSize; i++) {
61937 if(!UA_Variant_isEmpty(v: &ctx.valueResult[i]))
61938 UA_Variant_clear(p: &ctx.valueResult[i]);
61939 }
61940 return res;
61941}
61942
61943static UA_Boolean
61944isValidEvent(UA_Server *server, const UA_NodeId *validEventParent,
61945 const UA_NodeId *eventId) {
61946 /* find the eventType variableNode */
61947 UA_QualifiedName findName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType");
61948 UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: *eventId, browsePathSize: 1, browsePath: &findName);
61949 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
61950 UA_BrowsePathResult_clear(p: &bpr);
61951 return false;
61952 }
61953
61954 /* Get the EventType Property Node */
61955 UA_Variant tOutVariant;
61956 UA_Variant_init(p: &tOutVariant);
61957
61958 /* Read the Value of EventType Property Node (the Value should be a NodeId) */
61959 UA_StatusCode retval = readWithReadValue(server, nodeId: &bpr.targets[0].targetId.nodeId,
61960 attributeId: UA_ATTRIBUTEID_VALUE, v: &tOutVariant);
61961 if(retval != UA_STATUSCODE_GOOD ||
61962 !UA_Variant_hasScalarType(v: &tOutVariant, type: &UA_TYPES[UA_TYPES_NODEID])) {
61963 UA_BrowsePathResult_clear(p: &bpr);
61964 return false;
61965 }
61966
61967 const UA_NodeId *tEventType = (UA_NodeId*)tOutVariant.data;
61968
61969 /* check whether the EventType is a Subtype of CondtionType
61970 * (Part 9 first implementation) */
61971 UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_CONDITIONTYPE);
61972 if(UA_NodeId_equal(n1: validEventParent, n2: &conditionTypeId) &&
61973 isNodeInTree_singleRef(server, leafNode: tEventType, nodeToFind: &conditionTypeId,
61974 UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
61975 UA_BrowsePathResult_clear(p: &bpr);
61976 UA_Variant_clear(p: &tOutVariant);
61977 return true;
61978 }
61979
61980 /*EventType is not a Subtype of CondtionType
61981 *(ConditionId Clause won't be present in Events, which are not Conditions)*/
61982 /* check whether Valid Event other than Conditions */
61983 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
61984 UA_Boolean isSubtypeOfBaseEvent =
61985 isNodeInTree_singleRef(server, leafNode: tEventType, nodeToFind: &baseEventTypeId,
61986 UA_REFERENCETYPEINDEX_HASSUBTYPE);
61987
61988 UA_BrowsePathResult_clear(p: &bpr);
61989 UA_Variant_clear(p: &tOutVariant);
61990 return isSubtypeOfBaseEvent;
61991}
61992
61993UA_StatusCode
61994filterEvent(UA_Server *server, UA_Session *session,
61995 const UA_NodeId *eventNode, UA_EventFilter *filter,
61996 UA_EventFieldList *efl, UA_EventFilterResult *result) {
61997 if(filter->selectClausesSize == 0)
61998 return UA_STATUSCODE_BADEVENTFILTERINVALID;
61999
62000 UA_EventFieldList_init(p: efl);
62001 efl->eventFields = (UA_Variant *)
62002 UA_Array_new(size: filter->selectClausesSize, type: &UA_TYPES[UA_TYPES_VARIANT]);
62003 if(!efl->eventFields)
62004 return UA_STATUSCODE_BADOUTOFMEMORY;
62005 efl->eventFieldsSize = filter->selectClausesSize;
62006
62007 /* empty event filter result */
62008 UA_EventFilterResult_init(p: result);
62009 result->selectClauseResultsSize = filter->selectClausesSize;
62010 result->selectClauseResults = (UA_StatusCode *)
62011 UA_Array_new(size: filter->selectClausesSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
62012 if(!result->selectClauseResults) {
62013 UA_EventFieldList_clear(p: efl);
62014 UA_EventFilterResult_clear(p: result);
62015 return UA_STATUSCODE_BADOUTOFMEMORY;
62016 }
62017 /* prepare content filter result structure */
62018 if(filter->whereClause.elementsSize != 0) {
62019 result->whereClauseResult.elementResultsSize = filter->whereClause.elementsSize;
62020 result->whereClauseResult.elementResults = (UA_ContentFilterElementResult *)
62021 UA_Array_new(size: filter->whereClause.elementsSize,
62022 type: &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
62023 if(!result->whereClauseResult.elementResults) {
62024 UA_EventFieldList_clear(p: efl);
62025 UA_EventFilterResult_clear(p: result);
62026 return UA_STATUSCODE_BADOUTOFMEMORY;
62027 }
62028 for(size_t i = 0; i < result->whereClauseResult.elementResultsSize; ++i) {
62029 result->whereClauseResult.elementResults[i].operandStatusCodesSize =
62030 filter->whereClause.elements->filterOperandsSize;
62031 result->whereClauseResult.elementResults[i].operandStatusCodes =
62032 (UA_StatusCode *)UA_Array_new(
62033 size: filter->whereClause.elements->filterOperandsSize,
62034 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
62035 if(!result->whereClauseResult.elementResults[i].operandStatusCodes) {
62036 UA_EventFieldList_clear(p: efl);
62037 UA_EventFilterResult_clear(p: result);
62038 return UA_STATUSCODE_BADOUTOFMEMORY;
62039 }
62040 }
62041 }
62042
62043 /* Apply the content (where) filter */
62044 UA_StatusCode res =
62045 UA_Server_evaluateWhereClauseContentFilter(server, session, eventNode,
62046 contentFilter: &filter->whereClause, contentFilterResult: &result->whereClauseResult);
62047 if(res != UA_STATUSCODE_GOOD){
62048 UA_EventFieldList_clear(p: efl);
62049 UA_EventFilterResult_clear(p: result);
62050 return res;
62051 }
62052
62053 /* Apply the select filter */
62054 /* Check if the browsePath is BaseEventType, in which case nothing more
62055 * needs to be checked */
62056 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
62057 for(size_t i = 0; i < filter->selectClausesSize; i++) {
62058 if(!UA_NodeId_equal(n1: &filter->selectClauses[i].typeDefinitionId, n2: &baseEventTypeId) &&
62059 !isValidEvent(server, validEventParent: &filter->selectClauses[i].typeDefinitionId, eventId: eventNode)) {
62060 UA_Variant_init(p: &efl->eventFields[i]);
62061 /* EventFilterResult currently isn't being used
62062 notification->result.selectClauseResults[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; */
62063 continue;
62064 }
62065
62066 /* TODO: Put the result into the selectClausResults */
62067 resolveSimpleAttributeOperand(server, session, origin: eventNode,
62068 sao: &filter->selectClauses[i], value: &efl->eventFields[i]);
62069 }
62070
62071 return UA_STATUSCODE_GOOD;
62072}
62073
62074/*****************************************/
62075/* Validation of Filters during Creation */
62076/*****************************************/
62077
62078/* Initial select clause validation. The following checks are currently performed:
62079 * - Check if typedefenitionid or browsepath of any clause is NULL
62080 * - Check if the eventType is a subtype of BaseEventType
62081 * - Check if attributeId is valid
62082 * - Check if browsePath contains null
62083 * - Check if indexRange is defined and if it is parsable
62084 * - Check if attributeId is value */
62085void
62086UA_Event_staticSelectClauseValidation(UA_Server *server,
62087 const UA_EventFilter *eventFilter,
62088 UA_StatusCode *result) {
62089 /* The selectClause only has to be checked, if the size is not zero */
62090 if(eventFilter->selectClausesSize == 0)
62091 return;
62092 for(size_t i = 0; i < eventFilter->selectClausesSize; ++i) {
62093 result[i] = UA_STATUSCODE_GOOD;
62094 /* /typedefenitionid or browsepath of any clause is not NULL ? */
62095 if(UA_NodeId_isNull(p: &eventFilter->selectClauses[i].typeDefinitionId)) {
62096 result[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
62097 continue;
62098 }
62099 /*ToDo: Check the following workaround. In UaExpert Event View the selection
62100 * of the Server Object set up 7 select filter entries by default. The last
62101 * element ist from node 2782 (A&C ConditionType). Since the reduced
62102 * information model dos not contain this type, the result has a brows path of
62103 * "null" which results in an error. */
62104 UA_NodeId ac_conditionType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_CONDITIONTYPE);
62105 if(UA_NodeId_equal(n1: &eventFilter->selectClauses[i].typeDefinitionId, n2: &ac_conditionType)) {
62106 continue;
62107 }
62108 if(&eventFilter->selectClauses[i].browsePath[0] == NULL) {
62109 result[i] = UA_STATUSCODE_BADBROWSENAMEINVALID;
62110 continue;
62111 }
62112 /* eventType is a subtype of BaseEventType ? */
62113 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
62114 if(!isNodeInTree_singleRef(
62115 server, leafNode: &eventFilter->selectClauses[i].typeDefinitionId,
62116 nodeToFind: &baseEventTypeId, UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
62117 result[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
62118 continue;
62119 }
62120 /* attributeId is valid ? */
62121 if(!((0 < eventFilter->selectClauses[i].attributeId) &&
62122 (eventFilter->selectClauses[i].attributeId < 28))) {
62123 result[i] = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
62124 continue;
62125 }
62126 /* browsePath contains null ? */
62127 for(size_t j = 0; j < eventFilter->selectClauses[i].browsePathSize; ++j) {
62128 if(UA_QualifiedName_isNull(
62129 q: &eventFilter->selectClauses[i].browsePath[j])) {
62130 result[i] = UA_STATUSCODE_BADBROWSENAMEINVALID;
62131 break;
62132 }
62133 }
62134
62135 /* Get the list of Subtypes from current node */
62136 UA_ReferenceTypeSet reftypes_interface =
62137 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
62138 UA_ExpandedNodeId *chilTypeNodes = NULL;
62139 size_t chilTypeNodesSize = 0;
62140 UA_StatusCode res;
62141 res = browseRecursive(server, startNodesSize: 1, startNodes: &eventFilter->selectClauses[i].typeDefinitionId,
62142 browseDirection: UA_BROWSEDIRECTION_FORWARD, refTypes: &reftypes_interface, nodeClassMask: UA_NODECLASS_OBJECTTYPE,
62143 true, resultsSize: &chilTypeNodesSize, results: &chilTypeNodes);
62144 if(res!=UA_STATUSCODE_GOOD){
62145 result[i] = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
62146 continue;
62147 }
62148
62149 UA_Boolean subTypeContainField = false;
62150 for (size_t j = 0; j < chilTypeNodesSize; ++j) {
62151 /* browsPath element is defined in path */
62152 UA_BrowsePathResult bpr =
62153 browseSimplifiedBrowsePath(server, origin: chilTypeNodes[j].nodeId,
62154 browsePathSize: eventFilter->selectClauses[i].browsePathSize,
62155 browsePath: eventFilter->selectClauses[i].browsePath);
62156
62157 if(bpr.statusCode != UA_STATUSCODE_GOOD){
62158 UA_BrowsePathResult_clear(p: &bpr);
62159 continue;
62160 }
62161 subTypeContainField = true;
62162 UA_BrowsePathResult_clear(p: &bpr);
62163 }
62164 if(!subTypeContainField)
62165 result[i] = UA_STATUSCODE_BADNODEIDUNKNOWN;
62166
62167 UA_Array_delete(p: chilTypeNodes, size: chilTypeNodesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
62168
62169 if(result[i] != UA_STATUSCODE_GOOD)
62170 continue;
62171 /*indexRange is defined ? */
62172 if(!UA_String_equal(s1: &eventFilter->selectClauses[i].indexRange,
62173 s2: &UA_STRING_NULL)) {
62174 /* indexRange is parsable ? */
62175 UA_NumericRange numericRange = UA_NUMERICRANGE(s: "");
62176 if(UA_NumericRange_parse(range: &numericRange,
62177 str: eventFilter->selectClauses[i].indexRange) !=
62178 UA_STATUSCODE_GOOD) {
62179 result[i] = UA_STATUSCODE_BADINDEXRANGEINVALID;
62180 continue;
62181 }
62182 UA_free(ptr: numericRange.dimensions);
62183 /* attributeId is value ? */
62184 if(eventFilter->selectClauses[i].attributeId != UA_ATTRIBUTEID_VALUE) {
62185 result[i] = UA_STATUSCODE_BADTYPEMISMATCH;
62186 continue;
62187 }
62188 }
62189 }
62190}
62191
62192/* Initial content filter (where clause) check. Current checks:
62193 * - Number of operands for each (supported) operator */
62194UA_StatusCode
62195UA_Event_staticWhereClauseValidation(UA_Server *server,
62196 const UA_ContentFilter *filter,
62197 UA_ContentFilterResult *result) {
62198 UA_ContentFilterResult_init(p: result);
62199 result->elementResultsSize = filter->elementsSize;
62200 if(result->elementResultsSize == 0)
62201 return UA_STATUSCODE_GOOD;
62202 result->elementResults =
62203 (UA_ContentFilterElementResult *)UA_Array_new(
62204 size: result->elementResultsSize,
62205 type: &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
62206 if(!result->elementResults)
62207 return UA_STATUSCODE_BADOUTOFMEMORY;
62208 for(size_t i = 0; i < result->elementResultsSize; ++i) {
62209 UA_ContentFilterElementResult *er = &result->elementResults[i];
62210 UA_ContentFilterElement ef = filter->elements[i];
62211 UA_ContentFilterElementResult_init(p: er);
62212 er->operandStatusCodes =
62213 (UA_StatusCode *)UA_Array_new(
62214 size: ef.filterOperandsSize,
62215 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
62216 er->operandStatusCodesSize = ef.filterOperandsSize;
62217
62218 switch(ef.filterOperator) {
62219 case UA_FILTEROPERATOR_INVIEW:
62220 case UA_FILTEROPERATOR_RELATEDTO: {
62221 /* Not allowed for event WhereClause according to 7.17.3 in Part 4 */
62222 er->statusCode =
62223 UA_STATUSCODE_BADEVENTFILTERINVALID;
62224 break;
62225 }
62226 case UA_FILTEROPERATOR_EQUALS:
62227 case UA_FILTEROPERATOR_GREATERTHAN:
62228 case UA_FILTEROPERATOR_LESSTHAN:
62229 case UA_FILTEROPERATOR_GREATERTHANOREQUAL:
62230 case UA_FILTEROPERATOR_LESSTHANOREQUAL:
62231 case UA_FILTEROPERATOR_LIKE:
62232 case UA_FILTEROPERATOR_CAST:
62233 case UA_FILTEROPERATOR_BITWISEAND:
62234 case UA_FILTEROPERATOR_BITWISEOR: {
62235 if(ef.filterOperandsSize != 2) {
62236 er->statusCode =
62237 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62238 break;
62239 }
62240 er->statusCode = UA_STATUSCODE_GOOD;
62241 break;
62242 }
62243 case UA_FILTEROPERATOR_AND:
62244 case UA_FILTEROPERATOR_OR: {
62245 if(ef.filterOperandsSize != 2) {
62246 er->statusCode =
62247 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62248 break;
62249 }
62250 for(size_t j = 0; j < 2; ++j) {
62251 if(ef.filterOperands[j].content.decoded.type !=
62252 &UA_TYPES[UA_TYPES_ELEMENTOPERAND]) {
62253 er->operandStatusCodes[j] =
62254 UA_STATUSCODE_BADFILTEROPERANDINVALID;
62255 er->statusCode =
62256 UA_STATUSCODE_BADFILTEROPERANDINVALID;
62257 break;
62258 }
62259 if(((UA_ElementOperand *)ef.filterOperands[j]
62260 .content.decoded.data)->index > filter->elementsSize - 1) {
62261 er->operandStatusCodes[j] =
62262 UA_STATUSCODE_BADINDEXRANGEINVALID;
62263 er->statusCode =
62264 UA_STATUSCODE_BADINDEXRANGEINVALID;
62265 break;
62266 }
62267 }
62268 er->statusCode = UA_STATUSCODE_GOOD;
62269 break;
62270 }
62271 case UA_FILTEROPERATOR_ISNULL:
62272 case UA_FILTEROPERATOR_NOT: {
62273 if(ef.filterOperandsSize != 1) {
62274 er->statusCode =
62275 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62276 break;
62277 }
62278 er->statusCode = UA_STATUSCODE_GOOD;
62279 break;
62280 }
62281 case UA_FILTEROPERATOR_INLIST: {
62282 if(ef.filterOperandsSize <= 2) {
62283 er->statusCode =
62284 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62285 break;
62286 }
62287 er->statusCode = UA_STATUSCODE_GOOD;
62288 break;
62289 }
62290 case UA_FILTEROPERATOR_BETWEEN: {
62291 if(ef.filterOperandsSize != 3) {
62292 er->statusCode =
62293 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62294 break;
62295 }
62296 er->statusCode = UA_STATUSCODE_GOOD;
62297 break;
62298 }
62299 case UA_FILTEROPERATOR_OFTYPE: {
62300 if(ef.filterOperandsSize != 1) {
62301 er->statusCode =
62302 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62303 break;
62304 }
62305 er->operandStatusCodesSize = ef.filterOperandsSize;
62306 if(ef.filterOperands[0].content.decoded.type !=
62307 &UA_TYPES[UA_TYPES_LITERALOPERAND]) {
62308 er->statusCode =
62309 UA_STATUSCODE_BADFILTEROPERANDINVALID;
62310 break;
62311 }
62312 UA_LiteralOperand *literalOperand =
62313 (UA_LiteralOperand *)ef.filterOperands[0]
62314 .content.decoded.data;
62315
62316 /* Make sure the &pOperand->nodeId is a subtype of BaseEventType */
62317 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
62318 if(!isNodeInTree_singleRef(
62319 server, leafNode: (UA_NodeId *)literalOperand->value.data, nodeToFind: &baseEventTypeId,
62320 UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
62321 er->statusCode =
62322 UA_STATUSCODE_BADNODEIDINVALID;
62323 break;
62324 }
62325 er->statusCode = UA_STATUSCODE_GOOD;
62326 break;
62327 }
62328 default:
62329 er->statusCode =
62330 UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
62331 break;
62332 }
62333 }
62334 return UA_STATUSCODE_GOOD;
62335}
62336
62337#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
62338
62339/**** amalgamated original file "/plugins/crypto/openssl/securitypolicy_openssl_common.h" ****/
62340
62341/* This Source Code Form is subject to the terms of the Mozilla Public
62342 * License, v. 2.0. If a copy of the MPL was not distributed with this
62343 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
62344 *
62345 * Copyright 2020 (c) Wind River Systems, Inc.
62346 * Copyright 2020 (c) basysKom GmbH
62347 *
62348 */
62349
62350
62351
62352#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
62353
62354#include <openssl/x509.h>
62355#include <openssl/evp.h>
62356
62357_UA_BEGIN_DECLS
62358
62359void saveDataToFile(const char *fileName, const UA_ByteString *str);
62360void UA_Openssl_Init(void);
62361
62362UA_StatusCode
62363UA_copyCertificate(UA_ByteString *dst, const UA_ByteString *src);
62364
62365UA_StatusCode
62366UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(const UA_ByteString *msg,
62367 X509 *publicKeyX509,
62368 const UA_ByteString *signature);
62369UA_StatusCode
62370UA_Openssl_X509_GetCertificateThumbprint(const UA_ByteString *certficate,
62371 UA_ByteString *pThumbprint,
62372 bool bThumbPrint);
62373UA_StatusCode
62374UA_Openssl_RSA_Oaep_Decrypt(UA_ByteString *data,
62375 EVP_PKEY *privateKey);
62376UA_StatusCode
62377UA_Openssl_RSA_OAEP_Encrypt(UA_ByteString *data, /* The data that is encrypted.
62378 The encrypted data will overwrite
62379 the data that was supplied. */
62380 size_t paddingSize, X509 *publicX509);
62381
62382UA_StatusCode
62383UA_Openssl_Random_Key_PSHA256_Derive(const UA_ByteString *secret,
62384 const UA_ByteString *seed,
62385 UA_ByteString *out);
62386
62387UA_StatusCode
62388UA_Openssl_RSA_Public_GetKeyLength(X509 *publicKeyX509, UA_Int32 *keyLen);
62389
62390UA_StatusCode
62391UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(const UA_ByteString *data,
62392 EVP_PKEY *privateKey,
62393 UA_ByteString *outSignature);
62394
62395UA_StatusCode
62396UA_OpenSSL_HMAC_SHA256_Verify(const UA_ByteString *message,
62397 const UA_ByteString *key,
62398 const UA_ByteString *signature);
62399
62400UA_StatusCode
62401UA_OpenSSL_HMAC_SHA256_Sign(const UA_ByteString *message,
62402 const UA_ByteString *key,
62403 UA_ByteString *signature);
62404
62405UA_StatusCode
62406UA_OpenSSL_AES_256_CBC_Decrypt(const UA_ByteString *iv,
62407 const UA_ByteString *key,
62408 UA_ByteString *data /* [in/out]*/);
62409
62410UA_StatusCode
62411UA_OpenSSL_AES_256_CBC_Encrypt(const UA_ByteString *iv,
62412 const UA_ByteString *key,
62413 UA_ByteString *data /* [in/out]*/);
62414
62415UA_StatusCode
62416UA_OpenSSL_X509_compare(const UA_ByteString *cert, const X509 *b);
62417
62418UA_StatusCode
62419UA_Openssl_RSA_Private_GetKeyLength(EVP_PKEY *privateKey,
62420 UA_Int32 *keyLen) ;
62421
62422UA_StatusCode
62423UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify(const UA_ByteString *msg,
62424 X509 *publicKeyX509,
62425 const UA_ByteString *signature);
62426
62427UA_StatusCode
62428UA_Openssl_RSA_PKCS1_V15_SHA1_Sign(const UA_ByteString *message,
62429 EVP_PKEY *privateKey,
62430 UA_ByteString *outSignature);
62431UA_StatusCode
62432UA_Openssl_Random_Key_PSHA1_Derive(const UA_ByteString *secret,
62433 const UA_ByteString *seed,
62434 UA_ByteString *out);
62435UA_StatusCode
62436UA_OpenSSL_HMAC_SHA1_Verify(const UA_ByteString *message,
62437 const UA_ByteString *key,
62438 const UA_ByteString *signature);
62439
62440UA_StatusCode
62441UA_OpenSSL_HMAC_SHA1_Sign(const UA_ByteString *message,
62442 const UA_ByteString *key,
62443 UA_ByteString *signature);
62444
62445UA_StatusCode
62446UA_Openssl_RSA_PKCS1_V15_Decrypt(UA_ByteString *data,
62447 EVP_PKEY *privateKey);
62448
62449UA_StatusCode
62450UA_Openssl_RSA_PKCS1_V15_Encrypt(UA_ByteString *data,
62451 size_t paddingSize,
62452 X509 *publicX509);
62453
62454UA_StatusCode
62455UA_OpenSSL_AES_128_CBC_Decrypt(const UA_ByteString *iv,
62456 const UA_ByteString *key,
62457 UA_ByteString *data /* [in/out]*/);
62458
62459UA_StatusCode
62460UA_OpenSSL_AES_128_CBC_Encrypt(const UA_ByteString *iv,
62461 const UA_ByteString *key,
62462 UA_ByteString *data /* [in/out]*/);
62463
62464EVP_PKEY *
62465UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey);
62466
62467X509 *
62468UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate);
62469
62470X509 *
62471UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate);
62472
62473X509 *
62474UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate);
62475
62476UA_StatusCode
62477UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target);
62478
62479_UA_END_DECLS
62480
62481#endif /* defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
62482
62483
62484/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_version_abstraction.h" ****/
62485
62486/* This Source Code Form is subject to the terms of the Mozilla Public
62487 * License, v. 2.0. If a copy of the MPL was not distributed with this
62488 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
62489 *
62490 * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
62491 *
62492 */
62493
62494
62495#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
62496
62497#include <openssl/x509.h>
62498
62499#if !defined(OPENSSL_VERSION_NUMBER)
62500#error "OPENSSL_VERSION_NUMBER is not defined."
62501#endif
62502
62503#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
62504#define X509_STORE_CTX_set0_trusted_stack(STORE_CTX, CTX_SKTRUSTED) X509_STORE_CTX_trusted_stack(STORE_CTX, CTX_SKTRUSTED)
62505#endif
62506
62507#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
62508#define X509_STORE_CTX_get_check_issued(STORE_CTX) STORE_CTX->check_issued
62509#endif
62510
62511#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
62512#define get_pkey_rsa(evp) ((evp)->pkey.rsa)
62513#else
62514#define get_pkey_rsa(evp) EVP_PKEY_get0_RSA(evp)
62515#endif
62516
62517#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
62518#define X509_get0_subject_key_id(PX509_CERT) (const ASN1_OCTET_STRING *)X509_get_ext_d2i(PX509_CERT, NID_subject_key_identifier, NULL, NULL);
62519#endif
62520
62521#endif /* defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
62522
62523/**** amalgamated original file "/plugins/crypto/openssl/securitypolicy_openssl_common.c" ****/
62524
62525/* This Source Code Form is subject to the terms of the Mozilla Public
62526 * License, v. 2.0. If a copy of the MPL was not distributed with this
62527 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
62528 *
62529 * Copyright 2020 (c) Wind River Systems, Inc.
62530 * Copyright 2020 (c) basysKom GmbH
62531 * Copyright 2022 (c) Wind River Systems, Inc.
62532 */
62533
62534/*
62535modification history
62536--------------------
6253701feb20,lan written
62538*/
62539
62540
62541#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
62542
62543#include <openssl/rsa.h>
62544#include <openssl/evp.h>
62545#include <openssl/err.h>
62546#include <openssl/sha.h>
62547#include <openssl/x509.h>
62548#include <openssl/hmac.h>
62549#include <openssl/aes.h>
62550#include <openssl/pem.h>
62551
62552
62553#define SHA1_DIGEST_LENGTH 20 /* 160 bits */
62554#define RSA_DECRYPT_BUFFER_LENGTH 2048 /* bytes */
62555
62556
62557/** P_SHA256 Context */
62558typedef struct UA_Openssl_P_SHA256_Ctx_ {
62559 size_t seedLen;
62560 size_t secretLen;
62561 UA_Byte A[32]; /* 32 bytes of SHA256 output */
62562 /*
62563 char seed[seedLen];
62564 char secret[secretLen]; */
62565} UA_Openssl_P_SHA256_Ctx;
62566
62567#define UA_Openssl_P_SHA256_SEED(ctx) ((ctx)->A+32)
62568#define UA_Openssl_P_SHA256_SECRET(ctx) ((ctx)->A+32+(ctx)->seedLen)
62569
62570/** P_SHA1 Context */
62571typedef struct UA_Openssl_P_SHA1_Ctx_ {
62572 size_t seedLen;
62573 size_t secretLen;
62574 UA_Byte A[SHA1_DIGEST_LENGTH]; /* 20 bytes of SHA1 output */
62575 /*
62576 char seed[seedLen];
62577 char secret[secretLen]; */
62578} UA_Openssl_P_SHA1_Ctx;
62579
62580#define UA_Openssl_P_SHA1_SEED(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH)
62581#define UA_Openssl_P_SHA1_SECRET(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH +(ctx)->seedLen)
62582
62583void
62584UA_Openssl_Init (void) {
62585 /* VxWorks7 has initialized the openssl. */
62586#ifndef __VXWORKS__
62587 static UA_Int16 bInit = 0;
62588 if (bInit == 1)
62589 return;
62590#if defined(OPENSSL_API_COMPAT) && (OPENSSL_API_COMPAT < 0x10100000L)
62591 /* only needed, if OpenSSL < V1.1 */
62592 OpenSSL_add_all_algorithms ();
62593 ERR_load_crypto_strings ();
62594#endif
62595 bInit = 1;
62596#endif
62597}
62598
62599static int UA_OpenSSL_RSA_Key_Size (EVP_PKEY * key){
62600#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
62601 return EVP_PKEY_get_size (pkey: key);
62602#else
62603 return RSA_size (get_pkey_rsa(key));
62604#endif
62605}
62606
62607/* UA_copyCertificate - allocalte the buffer, copy the certificate and
62608 * add a NULL to the end
62609 */
62610
62611UA_StatusCode
62612UA_copyCertificate (UA_ByteString * dst,
62613 const UA_ByteString * src) {
62614 UA_StatusCode retval = UA_ByteString_allocBuffer (bs: dst, length: src->length + 1);
62615 if (retval != UA_STATUSCODE_GOOD)
62616 return retval;
62617 (void) memcpy (dest: dst->data, src: src->data, n: src->length);
62618 dst->data[dst->length - 1] = '\0';
62619 dst->length--;
62620
62621 return UA_STATUSCODE_GOOD;
62622}
62623
62624static UA_StatusCode
62625UA_OpenSSL_RSA_Public_Verify (const UA_ByteString * message,
62626 const EVP_MD * evpMd,
62627 X509 * publicKeyX509,
62628 UA_Int16 padding,
62629 const UA_ByteString * signature
62630 ) {
62631 EVP_MD_CTX * mdctx = NULL;
62632 int opensslRet;
62633 EVP_PKEY_CTX * evpKeyCtx;
62634 EVP_PKEY * evpPublicKey = NULL;
62635 UA_StatusCode ret;
62636
62637 mdctx = EVP_MD_CTX_create ();
62638 if (mdctx == NULL) {
62639 ret = UA_STATUSCODE_BADOUTOFMEMORY;
62640 goto errout;
62641 }
62642 evpPublicKey = X509_get_pubkey (x: publicKeyX509);
62643 if (evpPublicKey == NULL) {
62644 ret = UA_STATUSCODE_BADOUTOFMEMORY;
62645 goto errout;
62646 }
62647
62648 opensslRet = EVP_DigestVerifyInit (ctx: mdctx, pctx: &evpKeyCtx, type: evpMd, NULL,
62649 pkey: evpPublicKey);
62650 if (opensslRet != 1) {
62651 ret = UA_STATUSCODE_BADINTERNALERROR;
62652 goto errout;
62653 }
62654 EVP_PKEY_CTX_set_rsa_padding (ctx: evpKeyCtx, pad_mode: padding);
62655 opensslRet = EVP_DigestVerifyUpdate (ctx: mdctx, data: message->data, dsize: message->length);
62656 if (opensslRet != 1) {
62657 ret = UA_STATUSCODE_BADINTERNALERROR;
62658 goto errout;
62659 }
62660 opensslRet = EVP_DigestVerifyFinal(ctx: mdctx, sig: signature->data, siglen: signature->length);
62661 if (opensslRet != 1) {
62662 ret = UA_STATUSCODE_BADINTERNALERROR;
62663 goto errout;
62664 }
62665
62666 ret = UA_STATUSCODE_GOOD;
62667errout:
62668 if (evpPublicKey != NULL) {
62669 EVP_PKEY_free (pkey: evpPublicKey);
62670 }
62671 if (mdctx != NULL) {
62672 EVP_MD_CTX_destroy (mdctx);
62673 }
62674 return ret;
62675}
62676
62677UA_StatusCode
62678UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify (const UA_ByteString * msg,
62679 X509 * publicKeyX509,
62680 const UA_ByteString * signature
62681 ) {
62682 return UA_OpenSSL_RSA_Public_Verify (message: msg, evpMd: EVP_sha256(), publicKeyX509,
62683 NID_sha256, signature);
62684}
62685
62686/* Get certificate thumbprint, and allocate the buffer. */
62687
62688UA_StatusCode
62689UA_Openssl_X509_GetCertificateThumbprint (const UA_ByteString * certficate,
62690 UA_ByteString * pThumbprint,
62691 bool bThumbPrint) {
62692 if (bThumbPrint) {
62693 pThumbprint->length = SHA_DIGEST_LENGTH;
62694 UA_StatusCode ret = UA_ByteString_allocBuffer (bs: pThumbprint, length: pThumbprint->length);
62695 if (ret != UA_STATUSCODE_GOOD) {
62696 return ret;
62697 }
62698 }
62699 else {
62700 if (pThumbprint->length != SHA_DIGEST_LENGTH) {
62701 return UA_STATUSCODE_BADINTERNALERROR;
62702 }
62703 }
62704 X509 * x509Certificate = UA_OpenSSL_LoadCertificate(certificate: certficate);
62705
62706 if (x509Certificate == NULL) {
62707 if (bThumbPrint) {
62708 UA_ByteString_clear (p: pThumbprint);
62709 }
62710 return UA_STATUSCODE_BADINTERNALERROR;
62711 }
62712
62713 if (X509_digest (data: x509Certificate, type: EVP_sha1(), md: pThumbprint->data, NULL)
62714 != 1) {
62715 if (bThumbPrint) {
62716 UA_ByteString_clear (p: pThumbprint);
62717 }
62718 return UA_STATUSCODE_BADINTERNALERROR;
62719 }
62720 X509_free(a: x509Certificate);
62721
62722 return UA_STATUSCODE_GOOD;
62723}
62724
62725static UA_StatusCode
62726UA_Openssl_RSA_Private_Decrypt (UA_ByteString * data,
62727 EVP_PKEY * privateKey,
62728 UA_Int16 padding) {
62729 if (data == NULL || privateKey == NULL) {
62730 return UA_STATUSCODE_BADINVALIDARGUMENT;
62731 }
62732
62733 if (privateKey == NULL) {
62734 return UA_STATUSCODE_BADINVALIDARGUMENT;
62735 }
62736
62737 size_t keySize = (size_t) UA_OpenSSL_RSA_Key_Size (key: privateKey);
62738 size_t cipherOffset = 0;
62739 size_t outOffset = 0;
62740 unsigned char buf[RSA_DECRYPT_BUFFER_LENGTH];
62741 size_t decryptedBytes;
62742 EVP_PKEY_CTX * ctx;
62743 int opensslRet;
62744
62745 ctx = EVP_PKEY_CTX_new (pkey: privateKey, NULL);
62746 if (ctx == NULL) {
62747 return UA_STATUSCODE_BADOUTOFMEMORY;
62748 }
62749 opensslRet = EVP_PKEY_decrypt_init (ctx);
62750 if (opensslRet != 1)
62751 {
62752 EVP_PKEY_CTX_free (ctx);
62753 return UA_STATUSCODE_BADINTERNALERROR;
62754 }
62755 opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, pad_mode: padding);
62756 if (opensslRet != 1) {
62757 EVP_PKEY_CTX_free (ctx);
62758 return UA_STATUSCODE_BADINTERNALERROR;
62759 }
62760
62761 while (cipherOffset < data->length) {
62762 decryptedBytes = RSA_DECRYPT_BUFFER_LENGTH;
62763 opensslRet = EVP_PKEY_decrypt (ctx,
62764 out: buf, /* where to decrypt */
62765 outlen: &decryptedBytes,
62766 in: data->data + cipherOffset, /* what to decrypt */
62767 inlen: keySize
62768 );
62769 if (opensslRet != 1) {
62770 EVP_PKEY_CTX_free (ctx);
62771 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
62772 }
62773 (void) memcpy(dest: data->data + outOffset, src: buf, n: decryptedBytes);
62774 cipherOffset += (size_t) keySize;
62775 outOffset += decryptedBytes;
62776 }
62777 data->length = outOffset;
62778 EVP_PKEY_CTX_free (ctx);
62779
62780 return UA_STATUSCODE_GOOD;
62781}
62782
62783UA_StatusCode
62784UA_Openssl_RSA_Oaep_Decrypt (UA_ByteString * data,
62785 EVP_PKEY * privateKey) {
62786 return UA_Openssl_RSA_Private_Decrypt (data, privateKey,
62787 RSA_PKCS1_OAEP_PADDING);
62788}
62789
62790static UA_StatusCode
62791UA_Openssl_RSA_Public_Encrypt (const UA_ByteString * message,
62792 X509 * publicX509,
62793 UA_Int16 padding,
62794 size_t paddingSize,
62795 UA_ByteString * encrypted) {
62796 EVP_PKEY_CTX * ctx = NULL;
62797 EVP_PKEY * evpPublicKey = NULL;
62798 int opensslRet;
62799 UA_StatusCode ret;
62800 size_t encryptedTextLen = 0;
62801 size_t dataPos = 0;
62802 size_t encryptedPos = 0;
62803 size_t bytesToEncrypt = 0;
62804 size_t encryptedBlockSize = 0;
62805 size_t keySize = 0;
62806
62807 evpPublicKey = X509_get_pubkey (x: publicX509);
62808 if (evpPublicKey == NULL) {
62809 ret = UA_STATUSCODE_BADOUTOFMEMORY;
62810 goto errout;
62811 }
62812 ctx = EVP_PKEY_CTX_new (pkey: evpPublicKey, NULL);
62813 if (ctx == NULL) {
62814 ret = UA_STATUSCODE_BADOUTOFMEMORY;
62815 goto errout;
62816 }
62817 opensslRet = EVP_PKEY_encrypt_init (ctx);
62818 if (opensslRet != 1) {
62819 ret = UA_STATUSCODE_BADINTERNALERROR;
62820 goto errout;
62821 }
62822 opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, pad_mode: padding);
62823 if (opensslRet != 1) {
62824 ret = UA_STATUSCODE_BADINTERNALERROR;
62825 goto errout;
62826 }
62827
62828 /* get the encrypted block size */
62829
62830 keySize = (size_t) UA_OpenSSL_RSA_Key_Size (key: evpPublicKey);
62831 if (keySize == 0) {
62832 ret = UA_STATUSCODE_BADINTERNALERROR;
62833 goto errout;
62834 }
62835
62836 switch (padding) {
62837 case RSA_PKCS1_OAEP_PADDING:
62838 case RSA_PKCS1_PADDING:
62839 if (keySize <= paddingSize) {
62840 ret = UA_STATUSCODE_BADINTERNALERROR;
62841 goto errout;
62842 }
62843 encryptedBlockSize = keySize - paddingSize;
62844 break;
62845 default:
62846 ret = UA_STATUSCODE_BADNOTSUPPORTED;
62847 goto errout;
62848 break;
62849 }
62850
62851 /* encrypt in reverse order so that [data] may alias [encrypted] */
62852
62853 dataPos = message->length;
62854 encryptedPos = ((dataPos - 1) / encryptedBlockSize + 1) * keySize;
62855 bytesToEncrypt = (dataPos - 1) % encryptedBlockSize + 1;
62856 encryptedTextLen = encryptedPos;
62857
62858 while (dataPos > 0) {
62859 size_t outlen = keySize;
62860 encryptedPos -= keySize;
62861 dataPos -= bytesToEncrypt;
62862 opensslRet = EVP_PKEY_encrypt (ctx, out: encrypted->data + encryptedPos, outlen: &outlen,
62863 in: message->data + dataPos, inlen: bytesToEncrypt);
62864
62865 if (opensslRet != 1) {
62866 ret = UA_STATUSCODE_BADINTERNALERROR;
62867 goto errout;
62868 }
62869 bytesToEncrypt = encryptedBlockSize;
62870 }
62871 encrypted->length = encryptedTextLen;
62872
62873 ret = UA_STATUSCODE_GOOD;
62874errout:
62875 if (evpPublicKey != NULL) {
62876 EVP_PKEY_free (pkey: evpPublicKey);
62877 }
62878 if (ctx != NULL) {
62879 EVP_PKEY_CTX_free (ctx);
62880 }
62881 return ret;
62882}
62883
62884UA_StatusCode
62885UA_Openssl_RSA_OAEP_Encrypt (UA_ByteString * data,
62886 size_t paddingSize,
62887 X509 * publicX509) {
62888 UA_ByteString message;
62889 UA_StatusCode ret;
62890
62891 ret = UA_ByteString_copy (src: data, dst: &message);
62892 if (ret != UA_STATUSCODE_GOOD) {
62893 return ret;
62894 }
62895 ret = UA_Openssl_RSA_Public_Encrypt (message: &message, publicX509,
62896 RSA_PKCS1_OAEP_PADDING,
62897 paddingSize,
62898 encrypted: data);
62899 UA_ByteString_clear (p: &message);
62900 return ret;
62901}
62902
62903static UA_Openssl_P_SHA256_Ctx *
62904P_SHA256_Ctx_Create (const UA_ByteString * secret,
62905 const UA_ByteString * seed) {
62906 size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA256_Ctx) + secret->length +
62907 seed->length;
62908 UA_Openssl_P_SHA256_Ctx * ctx = (UA_Openssl_P_SHA256_Ctx *) UA_malloc (size: size);
62909 if (ctx == NULL) {
62910 return NULL;
62911 }
62912 ctx->secretLen = secret->length;
62913 ctx->seedLen = seed->length;
62914 (void) memcpy (UA_Openssl_P_SHA256_SEED(ctx), src: seed->data, n: seed->length);
62915 (void) memcpy (UA_Openssl_P_SHA256_SECRET(ctx), src: secret->data, n: secret->length);
62916 /* A(0) = seed
62917 A(n) = HMAC_HASH(secret, A(n-1)) */
62918
62919 if (HMAC (evp_md: EVP_sha256(), key: secret->data, key_len: (int) secret->length, data: seed->data,
62920 data_len: seed->length, md: ctx->A, NULL) == NULL) {
62921 UA_free (ptr: ctx);
62922 return NULL;
62923 }
62924
62925 return ctx;
62926}
62927
62928static UA_StatusCode
62929P_SHA256_Hash_Generate (UA_Openssl_P_SHA256_Ctx * ctx,
62930 UA_Byte * pHas
62931 ) {
62932 /* Calculate P_SHA256(n) = HMAC_SHA256(secret, A(n)+seed) */
62933 if (HMAC (evp_md: EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), key_len: (int) ctx->secretLen,
62934 data: ctx->A, data_len: sizeof (ctx->A) + ctx->seedLen, md: pHas, NULL) == NULL) {
62935 return UA_STATUSCODE_BADINTERNALERROR;
62936 }
62937
62938 /* Calculate A(n) = HMAC_SHA256(secret, A(n-1)) */
62939 if (HMAC (evp_md: EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), key_len: (int) ctx->secretLen,
62940 data: ctx->A, data_len: sizeof (ctx->A), md: ctx->A, NULL) == NULL) {
62941 return UA_STATUSCODE_BADINTERNALERROR;
62942 }
62943 return UA_STATUSCODE_GOOD;
62944}
62945
62946UA_StatusCode
62947UA_Openssl_Random_Key_PSHA256_Derive (const UA_ByteString * secret,
62948 const UA_ByteString * seed,
62949 UA_ByteString * out) {
62950 size_t keyLen = out->length;
62951 size_t iter = keyLen/32 + ((keyLen%32)?1:0);
62952 size_t bufferLen = iter * 32;
62953 size_t i;
62954 UA_StatusCode st;
62955
62956 UA_Byte * pBuffer = (UA_Byte *) UA_malloc (size: bufferLen);
62957 if (pBuffer == NULL) {
62958 return UA_STATUSCODE_BADOUTOFMEMORY;
62959 }
62960
62961 UA_Openssl_P_SHA256_Ctx * ctx = P_SHA256_Ctx_Create (secret, seed);
62962 if (ctx == NULL) {
62963 UA_free (ptr: pBuffer);
62964 return UA_STATUSCODE_BADOUTOFMEMORY;
62965 }
62966
62967 for (i = 0; i < iter; i++) {
62968 st = P_SHA256_Hash_Generate (ctx, pHas: pBuffer + (i * 32));
62969 if (st != UA_STATUSCODE_GOOD) {
62970 UA_free (ptr: pBuffer);
62971 UA_free (ptr: ctx);
62972 return st;
62973 }
62974 }
62975
62976 (void) memcpy (dest: out->data, src: pBuffer, n: keyLen);
62977 UA_free (ptr: pBuffer);
62978 UA_free (ptr: ctx);
62979 return UA_STATUSCODE_GOOD;
62980}
62981
62982/* return the key bytes */
62983UA_StatusCode
62984UA_Openssl_RSA_Public_GetKeyLength (X509 * publicKeyX509,
62985 UA_Int32 * keyLen) {
62986 EVP_PKEY * evpKey = X509_get_pubkey (x: publicKeyX509);
62987 if (evpKey == NULL) {
62988 return UA_STATUSCODE_BADINTERNALERROR;
62989 }
62990 *keyLen = UA_OpenSSL_RSA_Key_Size (key: evpKey);
62991
62992 EVP_PKEY_free (pkey: evpKey);
62993
62994 return UA_STATUSCODE_GOOD;
62995}
62996
62997UA_StatusCode
62998UA_Openssl_RSA_Private_GetKeyLength (EVP_PKEY * privateKey,
62999 UA_Int32 * keyLen) {
63000 if (privateKey == NULL) {
63001 return UA_STATUSCODE_BADINVALIDARGUMENT;
63002 }
63003 *keyLen = UA_OpenSSL_RSA_Key_Size (key: privateKey);
63004
63005 return UA_STATUSCODE_GOOD;
63006}
63007
63008static UA_StatusCode
63009UA_Openssl_RSA_Private_Sign (const UA_ByteString * message,
63010 EVP_PKEY * privateKey,
63011 const EVP_MD * evpMd,
63012 UA_Int16 padding,
63013 UA_ByteString * outSignature) {
63014 EVP_MD_CTX * mdctx = NULL;
63015 int opensslRet;
63016 EVP_PKEY_CTX * evpKeyCtx;
63017 UA_StatusCode ret;
63018
63019 mdctx = EVP_MD_CTX_create ();
63020 if (mdctx == NULL) {
63021 ret = UA_STATUSCODE_BADOUTOFMEMORY;
63022 goto errout;
63023 }
63024
63025 if (privateKey == NULL) {
63026 return UA_STATUSCODE_BADINVALIDARGUMENT;
63027 }
63028 opensslRet = EVP_DigestSignInit (ctx: mdctx, pctx: &evpKeyCtx, type: evpMd, NULL, pkey: privateKey);
63029 if (opensslRet != 1) {
63030 ret = UA_STATUSCODE_BADINTERNALERROR;
63031 goto errout;
63032 }
63033 EVP_PKEY_CTX_set_rsa_padding (ctx: evpKeyCtx, pad_mode: padding);
63034
63035 opensslRet = EVP_DigestSignUpdate (ctx: mdctx, data: message->data, dsize: message->length);
63036 if (opensslRet != 1) {
63037 ret = UA_STATUSCODE_BADINTERNALERROR;
63038 goto errout;
63039 }
63040 opensslRet = EVP_DigestSignFinal (ctx: mdctx, sigret: outSignature->data, siglen: &outSignature->length);
63041 if (opensslRet != 1) {
63042 ret = UA_STATUSCODE_BADINTERNALERROR;
63043 goto errout;
63044 }
63045
63046 ret = UA_STATUSCODE_GOOD;
63047errout:
63048 if (mdctx != NULL) {
63049 EVP_MD_CTX_destroy (mdctx);
63050 }
63051 return ret;
63052}
63053
63054UA_StatusCode
63055UA_Openssl_RSA_PKCS1_V15_SHA256_Sign (const UA_ByteString * message,
63056 EVP_PKEY * privateKey,
63057 UA_ByteString * outSignature) {
63058 return UA_Openssl_RSA_Private_Sign (message, privateKey, evpMd: EVP_sha256(),
63059 NID_sha256, outSignature);
63060}
63061
63062UA_StatusCode
63063UA_OpenSSL_HMAC_SHA256_Verify (const UA_ByteString * message,
63064 const UA_ByteString * key,
63065 const UA_ByteString * signature
63066 ) {
63067 unsigned char buf[SHA256_DIGEST_LENGTH] = {0};
63068 UA_ByteString mac = {SHA256_DIGEST_LENGTH, buf};
63069
63070 if (HMAC (evp_md: EVP_sha256(), key: key->data, key_len: (int) key->length, data: message->data, data_len: message->length,
63071 md: mac.data, md_len: (unsigned int *) &mac.length) == NULL) {
63072 return UA_STATUSCODE_BADINTERNALERROR;
63073 }
63074 if (UA_ByteString_equal (string1: signature, string2: &mac)) {
63075 return UA_STATUSCODE_GOOD;
63076 }
63077 else {
63078 return UA_STATUSCODE_BADINTERNALERROR;
63079 }
63080}
63081
63082UA_StatusCode
63083UA_OpenSSL_HMAC_SHA256_Sign (const UA_ByteString * message,
63084 const UA_ByteString * key,
63085 UA_ByteString * signature
63086 ) {
63087 if (HMAC (evp_md: EVP_sha256(), key: key->data, key_len: (int) key->length, data: message->data,
63088 data_len: message->length,
63089 md: signature->data, md_len: (unsigned int *) &(signature->length)) == NULL) {
63090 return UA_STATUSCODE_BADINTERNALERROR;
63091 }
63092 return UA_STATUSCODE_GOOD;
63093}
63094
63095static UA_StatusCode
63096UA_OpenSSL_Decrypt (const UA_ByteString * iv,
63097 const UA_ByteString * key,
63098 const EVP_CIPHER * cipherAlg,
63099 UA_ByteString * data /* [in/out]*/) {
63100 UA_ByteString ivCopy = {0, NULL};
63101 UA_ByteString cipherTxt = {0, NULL};
63102 EVP_CIPHER_CTX * ctx = NULL;
63103 UA_StatusCode ret;
63104 int opensslRet;
63105 int outLen;
63106 int tmpLen;
63107
63108 /* copy the IV because the AES_cbc_encrypt function overwrites it. */
63109
63110 ret = UA_ByteString_copy (src: iv, dst: &ivCopy);
63111 if (ret != UA_STATUSCODE_GOOD) {
63112 goto errout;
63113 }
63114
63115 ret = UA_ByteString_copy (src: data, dst: &cipherTxt);
63116 if (ret != UA_STATUSCODE_GOOD) {
63117 goto errout;
63118 }
63119
63120 ctx = EVP_CIPHER_CTX_new ();
63121 if (ctx == NULL) {
63122 ret = UA_STATUSCODE_BADOUTOFMEMORY;
63123 goto errout;
63124 }
63125
63126 /* call EVP_* to decrypt */
63127
63128 opensslRet = EVP_DecryptInit_ex (ctx, cipher: cipherAlg, NULL, key: key->data, iv: ivCopy.data);
63129 if (opensslRet != 1) {
63130 ret = UA_STATUSCODE_BADINTERNALERROR;
63131 goto errout;
63132 }
63133 /* EVP_DecryptFinal() will return an error code if padding is enabled
63134 * and the final block is not correctly formatted.
63135 */
63136 EVP_CIPHER_CTX_set_padding (c: ctx, pad: 0);
63137 opensslRet = EVP_DecryptUpdate (ctx, out: data->data, outl: &outLen,
63138 in: cipherTxt.data, inl: (int) cipherTxt.length);
63139 if (opensslRet != 1) {
63140 ret = UA_STATUSCODE_BADINTERNALERROR;
63141 goto errout;
63142 }
63143 opensslRet = EVP_DecryptFinal_ex (ctx, outm: data->data + outLen, outl: &tmpLen);
63144 if (opensslRet != 1) {
63145 ret = UA_STATUSCODE_BADINTERNALERROR;
63146 goto errout;
63147 }
63148 outLen += tmpLen;
63149 data->length = (size_t) outLen;
63150 ret = UA_STATUSCODE_GOOD;
63151
63152errout:
63153 UA_ByteString_clear (p: &ivCopy);
63154 UA_ByteString_clear (p: &cipherTxt);
63155 if (ctx != NULL) {
63156 EVP_CIPHER_CTX_free(c: ctx);
63157 }
63158 return ret;
63159}
63160
63161static UA_StatusCode
63162UA_OpenSSL_Encrypt (const UA_ByteString * iv,
63163 const UA_ByteString * key,
63164 const EVP_CIPHER * cipherAlg,
63165 UA_ByteString * data /* [in/out]*/
63166 ) {
63167
63168 UA_ByteString ivCopy = {0, NULL};
63169 UA_ByteString plainTxt = {0, NULL};
63170 EVP_CIPHER_CTX * ctx = NULL;
63171 UA_StatusCode ret;
63172 int opensslRet;
63173 int outLen;
63174 int tmpLen;
63175
63176 /* copy the IV because the AES_cbc_encrypt function overwrites it. */
63177
63178 ret = UA_ByteString_copy (src: iv, dst: &ivCopy);
63179 if (ret != UA_STATUSCODE_GOOD) {
63180 goto errout;
63181 }
63182
63183 ret = UA_ByteString_copy (src: data, dst: &plainTxt);
63184 if (ret != UA_STATUSCODE_GOOD) {
63185 goto errout;
63186 }
63187
63188 ctx = EVP_CIPHER_CTX_new ();
63189 if (ctx == NULL) {
63190 ret = UA_STATUSCODE_BADOUTOFMEMORY;
63191 goto errout;
63192 }
63193
63194 /* call EVP_* to encrypt */
63195
63196 opensslRet = EVP_EncryptInit_ex (ctx, cipher: cipherAlg, NULL, key: key->data, iv: ivCopy.data);
63197 if (opensslRet != 1) {
63198 ret = UA_STATUSCODE_BADINTERNALERROR;
63199 goto errout;
63200 }
63201
63202 /* Disable padding. Padding is done in the stack before calling encryption.
63203 * Ensure that we have a multiple of the block size */
63204 if(data->length % (size_t)EVP_CIPHER_CTX_block_size(ctx)) {
63205 ret = UA_STATUSCODE_BADINTERNALERROR;
63206 goto errout;
63207 }
63208 opensslRet = EVP_CIPHER_CTX_set_padding(c: ctx, pad: 0);
63209 if (opensslRet != 1) {
63210 ret = UA_STATUSCODE_BADINTERNALERROR;
63211 goto errout;
63212 }
63213
63214 /* Encrypt the data */
63215 opensslRet = EVP_EncryptUpdate (ctx, out: data->data, outl: &outLen,
63216 in: plainTxt.data, inl: (int) plainTxt.length);
63217 if (opensslRet != 1) {
63218 ret = UA_STATUSCODE_BADINTERNALERROR;
63219 goto errout;
63220 }
63221
63222 /* Encrypt-final does nothing as padding is disabled */
63223 opensslRet = EVP_EncryptFinal_ex(ctx, out: data->data + outLen, outl: &tmpLen);
63224 if (opensslRet != 1) {
63225 ret = UA_STATUSCODE_BADINTERNALERROR;
63226 goto errout;
63227 }
63228 outLen += tmpLen;
63229 data->length = (size_t) outLen;
63230 ret = UA_STATUSCODE_GOOD;
63231
63232errout:
63233 UA_ByteString_clear (p: &ivCopy);
63234 UA_ByteString_clear (p: &plainTxt);
63235 if (ctx != NULL) {
63236 EVP_CIPHER_CTX_free(c: ctx);
63237 }
63238 return ret;
63239}
63240
63241UA_StatusCode
63242UA_OpenSSL_AES_256_CBC_Decrypt (const UA_ByteString * iv,
63243 const UA_ByteString * key,
63244 UA_ByteString * data /* [in/out]*/
63245 ) {
63246 return UA_OpenSSL_Decrypt (iv, key, cipherAlg: EVP_aes_256_cbc (), data);
63247}
63248
63249UA_StatusCode
63250UA_OpenSSL_AES_256_CBC_Encrypt (const UA_ByteString * iv,
63251 const UA_ByteString * key,
63252 UA_ByteString * data /* [in/out]*/
63253 ) {
63254 return UA_OpenSSL_Encrypt (iv, key, cipherAlg: EVP_aes_256_cbc (), data);
63255}
63256
63257UA_StatusCode
63258UA_OpenSSL_X509_compare (const UA_ByteString * cert,
63259 const X509 * bcert) {
63260 X509 * acert = UA_OpenSSL_LoadCertificate(certificate: cert);
63261 if (acert == NULL) {
63262 return UA_STATUSCODE_BADCERTIFICATEINVALID;
63263 }
63264 int opensslRet = X509_cmp (a: acert, b: bcert);
63265 X509_free (a: acert);
63266
63267 if (opensslRet == 0)
63268 return UA_STATUSCODE_GOOD;
63269 return UA_STATUSCODE_UNCERTAINSUBNORMAL;
63270}
63271
63272UA_StatusCode
63273UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (const UA_ByteString * msg,
63274 X509 * publicKeyX509,
63275 const UA_ByteString * signature) {
63276 return UA_OpenSSL_RSA_Public_Verify (message: msg, evpMd: EVP_sha1(), publicKeyX509,
63277 NID_sha1, signature);
63278}
63279
63280UA_StatusCode
63281UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (const UA_ByteString * message,
63282 EVP_PKEY * privateKey,
63283 UA_ByteString * outSignature) {
63284 return UA_Openssl_RSA_Private_Sign (message, privateKey, evpMd: EVP_sha1(),
63285 NID_sha1, outSignature);
63286}
63287
63288static UA_Openssl_P_SHA1_Ctx *
63289P_SHA1_Ctx_Create (const UA_ByteString * secret,
63290 const UA_ByteString * seed) {
63291 size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA1_Ctx) + secret->length +
63292 seed->length;
63293 UA_Openssl_P_SHA1_Ctx * ctx = (UA_Openssl_P_SHA1_Ctx *) UA_malloc (size: size);
63294 if (ctx == NULL) {
63295 return NULL;
63296 }
63297
63298 ctx->secretLen = secret->length;
63299 ctx->seedLen = seed->length;
63300 (void) memcpy (UA_Openssl_P_SHA1_SEED(ctx), src: seed->data, n: seed->length);
63301 (void) memcpy (UA_Openssl_P_SHA1_SECRET(ctx), src: secret->data, n: secret->length);
63302 /* A(0) = seed
63303 A(n) = HMAC_HASH(secret, A(n-1)) */
63304
63305 if (HMAC (evp_md: EVP_sha1(), key: secret->data, key_len: (int) secret->length, data: seed->data,
63306 data_len: seed->length, md: ctx->A, NULL) == NULL) {
63307 UA_free (ptr: ctx);
63308 return NULL;
63309 }
63310
63311 return ctx;
63312}
63313
63314static UA_StatusCode
63315P_SHA1_Hash_Generate (UA_Openssl_P_SHA1_Ctx * ctx,
63316 UA_Byte * pHas
63317 ) {
63318 /* Calculate P_SHA1(n) = HMAC_SHA1(secret, A(n)+seed) */
63319 if (HMAC (evp_md: EVP_sha1 (), UA_Openssl_P_SHA1_SECRET(ctx), key_len: (int) ctx->secretLen,
63320 data: ctx->A, data_len: sizeof (ctx->A) + ctx->seedLen, md: pHas, NULL) == NULL) {
63321 return UA_STATUSCODE_BADINTERNALERROR;
63322 }
63323
63324 /* Calculate A(n) = HMAC_SHA1(secret, A(n-1)) */
63325 if (HMAC (evp_md: EVP_sha1(), UA_Openssl_P_SHA1_SECRET(ctx), key_len: (int) ctx->secretLen,
63326 data: ctx->A, data_len: sizeof (ctx->A), md: ctx->A, NULL) == NULL) {
63327 return UA_STATUSCODE_BADINTERNALERROR;
63328 }
63329 return UA_STATUSCODE_GOOD;
63330}
63331
63332UA_StatusCode
63333UA_Openssl_Random_Key_PSHA1_Derive (const UA_ByteString * secret,
63334 const UA_ByteString * seed,
63335 UA_ByteString * out) {
63336 size_t keyLen = out->length;
63337 size_t iter = keyLen / SHA1_DIGEST_LENGTH + ((keyLen % SHA1_DIGEST_LENGTH)?1:0);
63338 size_t bufferLen = iter * SHA1_DIGEST_LENGTH;
63339 UA_Byte * pBuffer = (UA_Byte *) UA_malloc (size: bufferLen);
63340 if (pBuffer == NULL) {
63341 return UA_STATUSCODE_BADOUTOFMEMORY;
63342 }
63343
63344 UA_Openssl_P_SHA1_Ctx * ctx = P_SHA1_Ctx_Create (secret, seed);
63345 if (ctx == NULL) {
63346 UA_free (ptr: pBuffer);
63347 return UA_STATUSCODE_BADOUTOFMEMORY;
63348 }
63349
63350 size_t i;
63351 UA_StatusCode st;
63352
63353 for (i = 0; i < iter; i++) {
63354 st = P_SHA1_Hash_Generate (ctx, pHas: pBuffer + (i * SHA1_DIGEST_LENGTH));
63355 if (st != UA_STATUSCODE_GOOD) {
63356 UA_free (ptr: pBuffer);
63357 UA_free (ptr: ctx);
63358 return st;
63359 }
63360 }
63361
63362 (void) memcpy (dest: out->data, src: pBuffer, n: keyLen);
63363 UA_free (ptr: pBuffer);
63364 UA_free (ptr: ctx);
63365
63366 return UA_STATUSCODE_GOOD;
63367}
63368
63369UA_StatusCode
63370UA_OpenSSL_HMAC_SHA1_Verify (const UA_ByteString * message,
63371 const UA_ByteString * key,
63372 const UA_ByteString * signature
63373 ) {
63374 unsigned char buf[SHA1_DIGEST_LENGTH] = {0};
63375 UA_ByteString mac = {SHA1_DIGEST_LENGTH, buf};
63376
63377 if(HMAC (evp_md: EVP_sha1(), key: key->data, key_len: (int) key->length, data: message->data, data_len: message->length,
63378 md: mac.data, md_len: (unsigned int *) &mac.length) == NULL) {
63379 return UA_STATUSCODE_BADINTERNALERROR;
63380 }
63381 if (UA_ByteString_equal (string1: signature, string2: &mac)) {
63382 return UA_STATUSCODE_GOOD;
63383 }
63384 else {
63385 return UA_STATUSCODE_BADINTERNALERROR;
63386 }
63387}
63388
63389UA_StatusCode
63390UA_OpenSSL_HMAC_SHA1_Sign (const UA_ByteString * message,
63391 const UA_ByteString * key,
63392 UA_ByteString * signature
63393 ) {
63394 if (HMAC (evp_md: EVP_sha1(), key: key->data, key_len: (int) key->length, data: message->data,
63395 data_len: message->length,
63396 md: signature->data, md_len: (unsigned int *) &(signature->length)) == NULL) {
63397 return UA_STATUSCODE_BADINTERNALERROR;
63398 }
63399 return UA_STATUSCODE_GOOD;
63400}
63401
63402UA_StatusCode
63403UA_Openssl_RSA_PKCS1_V15_Decrypt (UA_ByteString * data,
63404 EVP_PKEY * privateKey) {
63405 return UA_Openssl_RSA_Private_Decrypt (data, privateKey,
63406 RSA_PKCS1_PADDING);
63407}
63408
63409UA_StatusCode
63410UA_Openssl_RSA_PKCS1_V15_Encrypt (UA_ByteString * data,
63411 size_t paddingSize,
63412 X509 * publicX509) {
63413 UA_ByteString message;
63414 UA_StatusCode ret = UA_ByteString_copy (src: data, dst: &message);
63415 if (ret != UA_STATUSCODE_GOOD) {
63416 return ret;
63417 }
63418 ret = UA_Openssl_RSA_Public_Encrypt (message: &message, publicX509,
63419 RSA_PKCS1_PADDING,
63420 paddingSize,
63421 encrypted: data);
63422 UA_ByteString_clear (p: &message);
63423 return ret;
63424}
63425
63426UA_StatusCode
63427UA_OpenSSL_AES_128_CBC_Decrypt (const UA_ByteString * iv,
63428 const UA_ByteString * key,
63429 UA_ByteString * data /* [in/out]*/
63430 ) {
63431 return UA_OpenSSL_Decrypt (iv, key, cipherAlg: EVP_aes_128_cbc (), data);
63432}
63433
63434UA_StatusCode
63435UA_OpenSSL_AES_128_CBC_Encrypt (const UA_ByteString * iv,
63436 const UA_ByteString * key,
63437 UA_ByteString * data /* [in/out]*/
63438 ) {
63439 return UA_OpenSSL_Encrypt (iv, key, cipherAlg: EVP_aes_128_cbc (), data);
63440}
63441
63442EVP_PKEY *
63443UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey) {
63444 const unsigned char * pkData = privateKey->data;
63445 long len = (long) privateKey->length;
63446 if(len == 0)
63447 return NULL;
63448
63449 EVP_PKEY *result = NULL;
63450
63451 if (len > 1 && pkData[0] == 0x30 && pkData[1] == 0x82) { // Magic number for DER encoded keys
63452 result = d2i_PrivateKey(EVP_PKEY_RSA, NULL,
63453 pp: &pkData, length: len);
63454 } else {
63455 BIO *bio = NULL;
63456 bio = BIO_new_mem_buf(buf: (void *) privateKey->data, len: (int) privateKey->length);
63457 result = PEM_read_bio_PrivateKey(out: bio, NULL, NULL, NULL);
63458 BIO_free(a: bio);
63459 }
63460
63461 return result;
63462}
63463
63464X509 *
63465UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate) {
63466 X509 * result = NULL;
63467 const unsigned char *pData = certificate->data;
63468
63469 if (certificate->length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files
63470 result = UA_OpenSSL_LoadDerCertificate(certificate);
63471 } else {
63472 result = UA_OpenSSL_LoadPemCertificate(certificate);
63473 }
63474
63475 return result;
63476}
63477
63478X509 *
63479UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate) {
63480 const unsigned char *pData = certificate->data;
63481 return d2i_X509(NULL, in: &pData, len: (long) certificate->length);
63482}
63483
63484X509 *
63485UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate) {
63486 X509 * result = NULL;
63487
63488 BIO* bio = NULL;
63489 bio = BIO_new_mem_buf(buf: (void *) certificate->data, len: (int) certificate->length);
63490 result = PEM_read_bio_X509(out: bio, NULL, NULL, NULL);
63491 BIO_free(a: bio);
63492
63493 return result;
63494}
63495
63496UA_StatusCode
63497UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target) {
63498 X509 *cert = UA_OpenSSL_LoadCertificate(certificate);
63499
63500 if (!cert) {
63501 UA_ByteString_init(p: target);
63502 return UA_STATUSCODE_BADINVALIDARGUMENT;
63503 }
63504
63505 unsigned char *derData = NULL;
63506 int length = i2d_X509(a: cert, out: &derData);
63507 X509_free(a: cert);
63508
63509 if (length > 0) {
63510 UA_ByteString temp;
63511 temp.length = (size_t) length;
63512 temp.data = derData;
63513 UA_ByteString_copy(src: &temp, dst: target);
63514 OPENSSL_free(derData);
63515 return UA_STATUSCODE_GOOD;
63516 } else {
63517 UA_ByteString_init(p: target);
63518 }
63519
63520 return UA_STATUSCODE_BADINVALIDARGUMENT;
63521}
63522
63523#endif
63524
63525/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic128rsa15.c" ****/
63526
63527/* This Source Code Form is subject to the terms of the Mozilla Public
63528 * License, v. 2.0. If a copy of the MPL was not distributed with this
63529 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
63530 *
63531 * Copyright 2020 (c) Wind River Systems, Inc.
63532 * Copyright 2020 (c) basysKom GmbH
63533 */
63534
63535
63536#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
63537
63538
63539#include <openssl/x509.h>
63540#include <openssl/rand.h>
63541#include <openssl/evp.h>
63542
63543#define UA_SHA1_LENGTH 20
63544#define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11
63545#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH 16
63546#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE 16
63547#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH 16
63548#define UA_SHA1_LENGTH 20
63549
63550typedef struct {
63551 EVP_PKEY * localPrivateKey;
63552 UA_ByteString localCertThumbprint;
63553 const UA_Logger * logger;
63554} Policy_Context_Basic128Rsa15;
63555
63556typedef struct {
63557 UA_ByteString localSymSigningKey;
63558 UA_ByteString localSymEncryptingKey;
63559 UA_ByteString localSymIv;
63560 UA_ByteString remoteSymSigningKey;
63561 UA_ByteString remoteSymEncryptingKey;
63562 UA_ByteString remoteSymIv;
63563
63564 Policy_Context_Basic128Rsa15 * policyContext;
63565 UA_ByteString remoteCertificate;
63566 X509 * remoteCertificateX509;
63567} Channel_Context_Basic128Rsa15;
63568
63569static UA_StatusCode
63570UA_Policy_Basic128Rsa15_New_Context (UA_SecurityPolicy * securityPolicy,
63571 const UA_ByteString localPrivateKey,
63572 const UA_Logger * logger) {
63573 Policy_Context_Basic128Rsa15 * context = (Policy_Context_Basic128Rsa15 *)
63574 UA_malloc (size: sizeof (Policy_Context_Basic128Rsa15));
63575 if (context == NULL) {
63576 return UA_STATUSCODE_BADOUTOFMEMORY;
63577 }
63578
63579 context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey);
63580
63581 if (!context->localPrivateKey) {
63582 UA_free(ptr: context);
63583 return UA_STATUSCODE_BADINVALIDARGUMENT;
63584 }
63585
63586 UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
63587 certficate: &securityPolicy->localCertificate,
63588 pThumbprint: &context->localCertThumbprint, true
63589 );
63590 if (retval != UA_STATUSCODE_GOOD) {
63591 EVP_PKEY_free(pkey: context->localPrivateKey);
63592 UA_free (ptr: context);
63593 return retval;
63594 }
63595
63596 context->logger = logger;
63597 securityPolicy->policyContext = context;
63598
63599 return UA_STATUSCODE_GOOD;
63600}
63601
63602static void
63603UA_Policy_Basic128Rsa15_Clear_Context (UA_SecurityPolicy *policy) {
63604 if (policy == NULL) {
63605 return;
63606 }
63607 UA_ByteString_clear(p: &policy->localCertificate);
63608
63609 Policy_Context_Basic128Rsa15 * ctx = (Policy_Context_Basic128Rsa15 *) policy->policyContext;
63610 if (ctx == NULL) {
63611 return;
63612 }
63613
63614 /* delete all allocated members in the context */
63615
63616 EVP_PKEY_free(pkey: ctx->localPrivateKey);
63617 UA_ByteString_clear(p: &ctx->localCertThumbprint);
63618 UA_free (ptr: ctx);
63619
63620 return;
63621}
63622
63623/* create the channel context */
63624
63625static UA_StatusCode
63626UA_ChannelModule_Basic128Rsa15_New_Context (const UA_SecurityPolicy * securityPolicy,
63627 const UA_ByteString * remoteCertificate,
63628 void ** channelContext) {
63629 if (securityPolicy == NULL || remoteCertificate == NULL ||
63630 channelContext == NULL) {
63631 return UA_STATUSCODE_BADINTERNALERROR;
63632 }
63633 Channel_Context_Basic128Rsa15 * context = (Channel_Context_Basic128Rsa15 *)
63634 UA_malloc (size: sizeof (Channel_Context_Basic128Rsa15));
63635 if (context == NULL) {
63636 return UA_STATUSCODE_BADOUTOFMEMORY;
63637 }
63638
63639 UA_ByteString_init(p: &context->localSymSigningKey);
63640 UA_ByteString_init(p: &context->localSymEncryptingKey);
63641 UA_ByteString_init(p: &context->localSymIv);
63642 UA_ByteString_init(p: &context->remoteSymSigningKey);
63643 UA_ByteString_init(p: &context->remoteSymEncryptingKey);
63644 UA_ByteString_init(p: &context->remoteSymIv);
63645
63646 UA_StatusCode retval = UA_copyCertificate (dst: &context->remoteCertificate,
63647 src: remoteCertificate);
63648 if (retval != UA_STATUSCODE_GOOD) {
63649 UA_free (ptr: context);
63650 return retval;
63651 }
63652
63653 /* decode to X509 */
63654 context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate);
63655 if (context->remoteCertificateX509 == NULL) {
63656 UA_ByteString_clear (p: &context->remoteCertificate);
63657 UA_free (ptr: context);
63658 return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
63659 }
63660
63661 context->policyContext = (Policy_Context_Basic128Rsa15 *)
63662 (securityPolicy->policyContext);
63663
63664 *channelContext = context;
63665
63666 UA_LOG_INFO (logger: securityPolicy->logger,
63667 category: UA_LOGCATEGORY_SECURITYPOLICY,
63668 msg: "The Basic128Rsa15 security policy channel with openssl is created.");
63669
63670 return UA_STATUSCODE_GOOD;
63671}
63672
63673/* delete the channel context */
63674
63675static void
63676UA_ChannelModule_Basic128Rsa15_Delete_Context (void * channelContext) {
63677 if (channelContext != NULL) {
63678 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *)
63679 channelContext;
63680 X509_free (a: cc->remoteCertificateX509);
63681 UA_ByteString_clear (p: &cc->remoteCertificate);
63682 UA_ByteString_clear (p: &cc->localSymSigningKey);
63683 UA_ByteString_clear (p: &cc->localSymEncryptingKey);
63684 UA_ByteString_clear (p: &cc->localSymIv);
63685 UA_ByteString_clear (p: &cc->remoteSymSigningKey);
63686 UA_ByteString_clear (p: &cc->remoteSymEncryptingKey);
63687 UA_ByteString_clear (p: &cc->remoteSymIv);
63688 UA_LOG_INFO (logger: cc->policyContext->logger,
63689 category: UA_LOGCATEGORY_SECURITYPOLICY,
63690 msg: "The Basic128Rsa15 security policy channel with openssl is deleted.");
63691
63692 UA_free (ptr: cc);
63693 }
63694}
63695
63696static UA_StatusCode
63697UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey (void * channelContext,
63698 const UA_ByteString * key) {
63699 if (key == NULL || channelContext == NULL) {
63700 return UA_STATUSCODE_BADINVALIDARGUMENT;
63701 }
63702
63703 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63704 UA_ByteString_clear(p: &cc->localSymSigningKey);
63705 return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey);
63706}
63707
63708static UA_StatusCode
63709UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey (void * channelContext,
63710 const UA_ByteString * key) {
63711 if (key == NULL || channelContext == NULL) {
63712 return UA_STATUSCODE_BADINVALIDARGUMENT;
63713 }
63714
63715 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63716 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
63717 return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey);
63718}
63719
63720static UA_StatusCode
63721UA_ChannelModule_Basic128Rsa15_setLocalSymIv (void * channelContext,
63722 const UA_ByteString * iv) {
63723 if (iv == NULL || channelContext == NULL) {
63724 return UA_STATUSCODE_BADINVALIDARGUMENT;
63725 }
63726
63727 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63728 UA_ByteString_clear(p: &cc->localSymIv);
63729 return UA_ByteString_copy(src: iv, dst: &cc->localSymIv);
63730}
63731
63732static UA_StatusCode
63733UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey (void * channelContext,
63734 const UA_ByteString * key) {
63735 if (key == NULL || channelContext == NULL) {
63736 return UA_STATUSCODE_BADINVALIDARGUMENT;
63737 }
63738
63739 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63740 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
63741 return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey);
63742}
63743
63744static UA_StatusCode
63745UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey (void * channelContext,
63746 const UA_ByteString * key) {
63747 if (key == NULL || channelContext == NULL) {
63748 return UA_STATUSCODE_BADINVALIDARGUMENT;
63749 }
63750
63751 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63752 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
63753 return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey);
63754}
63755
63756static UA_StatusCode
63757UA_ChannelModule_Basic128Rsa15_setRemoteSymIv (void * channelContext,
63758 const UA_ByteString * key) {
63759 if (key == NULL || channelContext == NULL) {
63760 return UA_STATUSCODE_BADINVALIDARGUMENT;
63761 }
63762
63763 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63764 UA_ByteString_clear(p: &cc->remoteSymIv);
63765 return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv);
63766}
63767
63768static UA_StatusCode
63769UA_ChannelModule_Basic128Rsa15_compareCertificate (const void * channelContext,
63770 const UA_ByteString * certificate) {
63771 if(channelContext == NULL || certificate == NULL) {
63772 return UA_STATUSCODE_BADINVALIDARGUMENT;
63773 }
63774
63775 const Channel_Context_Basic128Rsa15 * cc =
63776 (const Channel_Context_Basic128Rsa15 *) channelContext;
63777 return UA_OpenSSL_X509_compare (cert: certificate, bcert: cc->remoteCertificateX509);
63778}
63779
63780static UA_StatusCode
63781UA_Asy_Basic128Rsa15_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
63782 const UA_ByteString * certificateThumbprint) {
63783 if (securityPolicy == NULL || certificateThumbprint == NULL) {
63784 return UA_STATUSCODE_BADINVALIDARGUMENT;
63785 }
63786 Policy_Context_Basic128Rsa15 *pc = (Policy_Context_Basic128Rsa15 *)
63787 securityPolicy->policyContext;
63788 if(!UA_ByteString_equal(string1: certificateThumbprint, string2: &pc->localCertThumbprint)) {
63789 return UA_STATUSCODE_BADCERTIFICATEINVALID;
63790 }
63791 return UA_STATUSCODE_GOOD;
63792}
63793
63794/* Generates a thumbprint for the specified certificate */
63795
63796static UA_StatusCode
63797UA_Asy_Basic128Rsa15_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
63798 const UA_ByteString * certificate,
63799 UA_ByteString * thumbprint) {
63800 return UA_Openssl_X509_GetCertificateThumbprint (certficate: certificate,
63801 pThumbprint: thumbprint, false);
63802}
63803
63804static size_t
63805UA_AsySig_Basic128Rsa15_getRemoteSignatureSize (const void * channelContext) {
63806 if (channelContext == NULL) {
63807 return UA_STATUSCODE_BADINVALIDARGUMENT;
63808 }
63809
63810 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63811 UA_Int32 keyLen = 0;
63812 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
63813 return (size_t) keyLen;
63814}
63815
63816static size_t
63817UA_AsySig_Basic128Rsa15_getLocalSignatureSize (const void * channelContext) {
63818 if (channelContext == NULL) {
63819 return UA_STATUSCODE_BADINVALIDARGUMENT;
63820 }
63821
63822 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63823 Policy_Context_Basic128Rsa15 * pc = (Policy_Context_Basic128Rsa15 *) cc->policyContext;
63824 UA_Int32 keyLen = 0;
63825 UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen);
63826
63827 return (size_t) keyLen;
63828}
63829
63830static UA_StatusCode
63831UA_AsySig_Basic128Rsa15_Verify (void * channelContext,
63832 const UA_ByteString * message,
63833 const UA_ByteString * signature) {
63834 if (message == NULL || signature == NULL ||
63835 channelContext == NULL) {
63836 return UA_STATUSCODE_BADINVALIDARGUMENT;
63837 }
63838
63839 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63840 UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (msg: message,
63841 publicKeyX509: cc->remoteCertificateX509, signature);
63842
63843 return retval;
63844}
63845
63846static UA_StatusCode
63847UA_AsySig_Basic128Rsa15_Sign (void * channelContext,
63848 const UA_ByteString * message,
63849 UA_ByteString * signature) {
63850 if (channelContext == NULL || message == NULL || signature == NULL) {
63851 return UA_STATUSCODE_BADINVALIDARGUMENT;
63852 }
63853
63854 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63855 Policy_Context_Basic128Rsa15 *pc = cc->policyContext;
63856 return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, privateKey: pc->localPrivateKey, outSignature: signature);
63857}
63858
63859static size_t
63860UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize (const void *channelContext) {
63861 if (channelContext == NULL) {
63862 return UA_STATUSCODE_BADINVALIDARGUMENT;
63863 }
63864
63865 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63866 UA_Int32 keyLen = 0;
63867 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
63868 return (size_t) keyLen - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
63869}
63870
63871static size_t
63872UA_AsymEn_Basic128Rsa15_getRemoteBlockSize (const void *channelContext) {
63873 if (channelContext == NULL) {
63874 return UA_STATUSCODE_BADINVALIDARGUMENT;
63875 }
63876
63877 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63878 UA_Int32 keyLen = 0;
63879 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
63880 return (size_t) keyLen;
63881}
63882
63883static size_t
63884UA_AsymEn_Basic128Rsa15_getRemoteKeyLength (const void *channelContext) {
63885 if (channelContext == NULL)
63886 return UA_STATUSCODE_BADINVALIDARGUMENT;
63887
63888 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63889 UA_Int32 keyLen = 0;
63890 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
63891 return (size_t) keyLen * 8;
63892}
63893
63894static size_t
63895UA_AsymEn_Basic128Rsa15_getLocalKeyLength (const void *channelContext) {
63896 if (channelContext == NULL)
63897 return UA_STATUSCODE_BADINVALIDARGUMENT;
63898
63899 const Channel_Context_Basic128Rsa15 *cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63900 Policy_Context_Basic128Rsa15 *pc = cc->policyContext;
63901 UA_Int32 keyLen = 0;
63902 UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen);
63903 return (size_t) keyLen * 8;
63904}
63905
63906static UA_StatusCode
63907UA_AsymEn_Basic128Rsa15_Decrypt (void * channelContext,
63908 UA_ByteString * data) {
63909 if (channelContext == NULL || data == NULL) {
63910 return UA_STATUSCODE_BADINVALIDARGUMENT;
63911 }
63912
63913 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63914 UA_StatusCode ret = UA_Openssl_RSA_PKCS1_V15_Decrypt (data,
63915 privateKey: cc->policyContext->localPrivateKey);
63916 return ret;
63917}
63918
63919static UA_StatusCode
63920UA_AsymEn_Basic128Rsa15_Encrypt (void * channelContext,
63921 UA_ByteString * data) {
63922 if (channelContext == NULL || data == NULL)
63923 return UA_STATUSCODE_BADINVALIDARGUMENT;
63924
63925 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63926 return UA_Openssl_RSA_PKCS1_V15_Encrypt (data,
63927 UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN,
63928 publicX509: cc->remoteCertificateX509);
63929}
63930
63931static UA_StatusCode
63932UA_Sym_Basic128Rsa15_generateNonce(void *policyContext,
63933 UA_ByteString *out) {
63934 UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length);
63935 if (rc != 1) {
63936 return UA_STATUSCODE_BADUNEXPECTEDERROR;
63937 }
63938 return UA_STATUSCODE_GOOD;
63939}
63940
63941static UA_StatusCode
63942UA_Sym_Basic128Rsa15_generateKey(void *policyContext,
63943 const UA_ByteString *secret,
63944 const UA_ByteString *seed,
63945 UA_ByteString *out) {
63946 return UA_Openssl_Random_Key_PSHA1_Derive(secret, seed, out);
63947}
63948
63949static size_t
63950UA_SymEn_Basic128Rsa15_getLocalKeyLength (const void *channelContext) {
63951 /* 16 bytes 128 bits */
63952 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH;
63953}
63954
63955static size_t
63956UA_SymEn_Basic128Rsa15_getBlockSize (const void *channelContext) {
63957 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
63958}
63959
63960static size_t
63961UA_SymEn_Basic128Rsa15_getRemoteKeyLength (const void * channelContext) {
63962 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH;
63963}
63964
63965static UA_StatusCode
63966UA_SymEn_Basic128Rsa15_Encrypt (void *channelContext,
63967 UA_ByteString *data) {
63968 if(channelContext == NULL || data == NULL)
63969 return UA_STATUSCODE_BADINVALIDARGUMENT;
63970
63971 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63972 return UA_OpenSSL_AES_128_CBC_Encrypt (iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data);
63973}
63974
63975static UA_StatusCode
63976UA_SymEn_Basic128Rsa15_Decrypt (void * channelContext,
63977 UA_ByteString * data) {
63978 if(channelContext == NULL || data == NULL)
63979 return UA_STATUSCODE_BADINVALIDARGUMENT;
63980 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63981 return UA_OpenSSL_AES_128_CBC_Decrypt (iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey, data);
63982}
63983
63984static size_t
63985UA_SymSig_Basic128Rsa15_getKeyLength (const void *channelContext) {
63986 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH;
63987}
63988
63989static size_t
63990UA_SymSig_Basic128Rsa15_getSignatureSize (const void *channelContext) {
63991 return UA_SHA1_LENGTH;
63992}
63993
63994static UA_StatusCode
63995UA_SymSig_Basic128Rsa15_Verify (void * channelContext,
63996 const UA_ByteString * message,
63997 const UA_ByteString * signature) {
63998 if (channelContext == NULL || message == NULL || signature == NULL)
63999 return UA_STATUSCODE_BADINVALIDARGUMENT;
64000
64001 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64002 return UA_OpenSSL_HMAC_SHA1_Verify (message,
64003 key: &cc->remoteSymSigningKey,
64004 signature);
64005}
64006
64007static UA_StatusCode
64008UA_SymSig_Basic128Rsa15_Sign (void * channelContext,
64009 const UA_ByteString * message,
64010 UA_ByteString * signature) {
64011 if (channelContext == NULL || message == NULL || signature == NULL)
64012 return UA_STATUSCODE_BADINVALIDARGUMENT;
64013
64014 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64015 return UA_OpenSSL_HMAC_SHA1_Sign (message, key: &cc->localSymSigningKey, signature);
64016}
64017
64018/* the main entry of Basic128Rsa15 */
64019
64020UA_StatusCode
64021UA_SecurityPolicy_Basic128Rsa15 (UA_SecurityPolicy * policy,
64022 const UA_ByteString localCertificate,
64023 const UA_ByteString localPrivateKey,
64024 const UA_Logger * logger) {
64025
64026 UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
64027 UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
64028 UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
64029 UA_StatusCode retval;
64030
64031 UA_LOG_INFO (logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
64032 msg: "The Basic128Rsa15 security policy with openssl is added.");
64033
64034 UA_Openssl_Init ();
64035 memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy));
64036 policy->logger = logger;
64037 policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0");
64038
64039 /* set ChannelModule context */
64040
64041 channelModule->newContext = UA_ChannelModule_Basic128Rsa15_New_Context;
64042 channelModule->deleteContext = UA_ChannelModule_Basic128Rsa15_Delete_Context;
64043
64044 channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey;
64045 channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey;
64046 channelModule->setLocalSymIv = UA_ChannelModule_Basic128Rsa15_setLocalSymIv;
64047 channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey;
64048 channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey;
64049 channelModule->setRemoteSymIv = UA_ChannelModule_Basic128Rsa15_setRemoteSymIv;
64050 channelModule->compareCertificate = UA_ChannelModule_Basic128Rsa15_compareCertificate;
64051
64052 retval = UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate);
64053
64054 if (retval != UA_STATUSCODE_GOOD)
64055 return retval;
64056
64057 /* asymmetricModule */
64058
64059 asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic128Rsa15_compareCertificateThumbprint;
64060 asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic128Rsa15_makeCertificateThumbprint;
64061
64062 /* AsymmetricModule - signature algorithm */
64063
64064 UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
64065 &asymmetricModule->cryptoModule.signatureAlgorithm;
64066 asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
64067 asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic128Rsa15_getRemoteSignatureSize;
64068 asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic128Rsa15_getLocalSignatureSize;
64069 asySigAlgorithm->getLocalKeyLength = NULL;
64070 asySigAlgorithm->getRemoteKeyLength = NULL;
64071 asySigAlgorithm->verify = UA_AsySig_Basic128Rsa15_Verify;
64072 asySigAlgorithm->sign = UA_AsySig_Basic128Rsa15_Sign;
64073
64074 /* AsymmetricModule encryption algorithm */
64075
64076 UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
64077 &asymmetricModule->cryptoModule.encryptionAlgorithm;
64078 asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-1_5\0");
64079 asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize;
64080 asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic128Rsa15_getRemoteBlockSize;
64081 asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic128Rsa15_getRemoteKeyLength;
64082 asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic128Rsa15_getLocalKeyLength;
64083 asymEncryAlg->decrypt = UA_AsymEn_Basic128Rsa15_Decrypt;
64084 asymEncryAlg->encrypt = UA_AsymEn_Basic128Rsa15_Encrypt;
64085
64086 /* SymmetricModule */
64087
64088 symmetricModule->secureChannelNonceLength = 16; /* 128 bits*/
64089 symmetricModule->generateNonce = UA_Sym_Basic128Rsa15_generateNonce;
64090 symmetricModule->generateKey = UA_Sym_Basic128Rsa15_generateKey;
64091
64092 /* Symmetric encryption Algorithm */
64093
64094 UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
64095 &symmetricModule->cryptoModule.encryptionAlgorithm;
64096 symEncryptionAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes128-cbc\0");
64097 symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic128Rsa15_getLocalKeyLength;
64098 symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic128Rsa15_getRemoteKeyLength;
64099 symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize;
64100 symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize;
64101 symEncryptionAlgorithm->decrypt = UA_SymEn_Basic128Rsa15_Decrypt;
64102 symEncryptionAlgorithm->encrypt = UA_SymEn_Basic128Rsa15_Encrypt;
64103
64104 /* Symmetric signature Algorithm */
64105
64106 UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
64107 &symmetricModule->cryptoModule.signatureAlgorithm;
64108 symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
64109 symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength;
64110 symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength;
64111 symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize;
64112 symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize;
64113
64114 symSignatureAlgorithm->verify = UA_SymSig_Basic128Rsa15_Verify;
64115 symSignatureAlgorithm->sign = UA_SymSig_Basic128Rsa15_Sign;
64116
64117 /* set the policy context */
64118
64119 retval = UA_Policy_Basic128Rsa15_New_Context (securityPolicy: policy, localPrivateKey, logger);
64120 if (retval != UA_STATUSCODE_GOOD) {
64121 UA_ByteString_clear (p: &policy->localCertificate);
64122 return retval;
64123 }
64124 policy->clear = UA_Policy_Basic128Rsa15_Clear_Context;
64125
64126 /* Use the same signature algorithm as the asymmetric component for
64127 certificate signing (see standard) */
64128 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
64129
64130 return UA_STATUSCODE_GOOD;
64131}
64132
64133#endif
64134
64135/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic256.c" ****/
64136
64137/* This Source Code Form is subject to the terms of the Mozilla Public
64138 * License, v. 2.0. If a copy of the MPL was not distributed with this
64139 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
64140 *
64141 * Copyright 2020 (c) Wind River Systems, Inc.
64142 * Copyright 2020 (c) basysKom GmbH
64143 */
64144
64145
64146#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
64147
64148
64149#include <openssl/x509.h>
64150#include <openssl/rand.h>
64151
64152#define UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN 42
64153#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH 32
64154#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE 16
64155#define UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH 24
64156#define UA_SHA1_LENGTH 20
64157
64158typedef struct {
64159 EVP_PKEY * localPrivateKey;
64160 UA_ByteString localCertThumbprint;
64161 const UA_Logger * logger;
64162} Policy_Context_Basic256;
64163
64164typedef struct {
64165 UA_ByteString localSymSigningKey;
64166 UA_ByteString localSymEncryptingKey;
64167 UA_ByteString localSymIv;
64168 UA_ByteString remoteSymSigningKey;
64169 UA_ByteString remoteSymEncryptingKey;
64170 UA_ByteString remoteSymIv;
64171
64172 Policy_Context_Basic256 * policyContext;
64173 UA_ByteString remoteCertificate;
64174 X509 * remoteCertificateX509;
64175} Channel_Context_Basic256;
64176
64177static UA_StatusCode
64178UA_Policy_Basic256_New_Context (UA_SecurityPolicy * securityPolicy,
64179 const UA_ByteString localPrivateKey,
64180 const UA_Logger * logger) {
64181 Policy_Context_Basic256 * context = (Policy_Context_Basic256 *)
64182 UA_malloc (size: sizeof (Policy_Context_Basic256));
64183 if (context == NULL) {
64184 return UA_STATUSCODE_BADOUTOFMEMORY;
64185 }
64186
64187 context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey);
64188
64189 if (!context->localPrivateKey) {
64190 UA_free (ptr: context);
64191 return UA_STATUSCODE_BADINVALIDARGUMENT;
64192 }
64193
64194 UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
64195 certficate: &securityPolicy->localCertificate,
64196 pThumbprint: &context->localCertThumbprint, true
64197 );
64198 if (retval != UA_STATUSCODE_GOOD) {
64199 EVP_PKEY_free(pkey: context->localPrivateKey);
64200 UA_free (ptr: context);
64201 return retval;
64202 }
64203
64204 context->logger = logger;
64205 securityPolicy->policyContext = context;
64206
64207 return UA_STATUSCODE_GOOD;
64208}
64209
64210static void
64211UA_Policy_Basic256_Clear_Context (UA_SecurityPolicy *policy) {
64212 if (policy == NULL) {
64213 return;
64214 }
64215 UA_ByteString_clear(p: &policy->localCertificate);
64216
64217 Policy_Context_Basic256 * ctx = (Policy_Context_Basic256 *) policy->policyContext;
64218 if (ctx == NULL) {
64219 return;
64220 }
64221
64222 /* delete all allocated members in the context */
64223
64224 EVP_PKEY_free(pkey: ctx->localPrivateKey);
64225 UA_ByteString_clear(p: &ctx->localCertThumbprint);
64226 UA_free (ptr: ctx);
64227
64228 return;
64229}
64230
64231/* create the channel context */
64232
64233static UA_StatusCode
64234UA_ChannelModule_Basic256_New_Context (const UA_SecurityPolicy * securityPolicy,
64235 const UA_ByteString * remoteCertificate,
64236 void ** channelContext) {
64237 if (securityPolicy == NULL || remoteCertificate == NULL ||
64238 channelContext == NULL) {
64239 return UA_STATUSCODE_BADINTERNALERROR;
64240 }
64241 Channel_Context_Basic256 * context = (Channel_Context_Basic256 *)
64242 UA_malloc (size: sizeof (Channel_Context_Basic256));
64243 if (context == NULL) {
64244 return UA_STATUSCODE_BADOUTOFMEMORY;
64245 }
64246
64247 UA_ByteString_init(p: &context->localSymSigningKey);
64248 UA_ByteString_init(p: &context->localSymEncryptingKey);
64249 UA_ByteString_init(p: &context->localSymIv);
64250 UA_ByteString_init(p: &context->remoteSymSigningKey);
64251 UA_ByteString_init(p: &context->remoteSymEncryptingKey);
64252 UA_ByteString_init(p: &context->remoteSymIv);
64253
64254 UA_StatusCode retval = UA_copyCertificate (dst: &context->remoteCertificate,
64255 src: remoteCertificate);
64256 if (retval != UA_STATUSCODE_GOOD) {
64257 UA_free (ptr: context);
64258 return retval;
64259 }
64260
64261 /* decode to X509 */
64262 context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate);
64263 if (context->remoteCertificateX509 == NULL) {
64264 UA_ByteString_clear (p: &context->remoteCertificate);
64265 UA_free (ptr: context);
64266 return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
64267 }
64268
64269 context->policyContext = (Policy_Context_Basic256 *)
64270 (securityPolicy->policyContext);
64271
64272 *channelContext = context;
64273
64274 UA_LOG_INFO (logger: securityPolicy->logger,
64275 category: UA_LOGCATEGORY_SECURITYPOLICY,
64276 msg: "The basic256 security policy channel with openssl is created.");
64277
64278 return UA_STATUSCODE_GOOD;
64279}
64280
64281/* delete the channel context */
64282
64283static void
64284UA_ChannelModule_Basic256_Delete_Context (void * channelContext) {
64285 if (channelContext != NULL) {
64286 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *)
64287 channelContext;
64288 X509_free (a: cc->remoteCertificateX509);
64289 UA_ByteString_clear (p: &cc->remoteCertificate);
64290 UA_ByteString_clear (p: &cc->localSymSigningKey);
64291 UA_ByteString_clear (p: &cc->localSymEncryptingKey);
64292 UA_ByteString_clear (p: &cc->localSymIv);
64293 UA_ByteString_clear (p: &cc->remoteSymSigningKey);
64294 UA_ByteString_clear (p: &cc->remoteSymEncryptingKey);
64295 UA_ByteString_clear (p: &cc->remoteSymIv);
64296 UA_LOG_INFO (logger: cc->policyContext->logger,
64297 category: UA_LOGCATEGORY_SECURITYPOLICY,
64298 msg: "The basic256 security policy channel with openssl is deleted.");
64299
64300 UA_free (ptr: cc);
64301 }
64302}
64303
64304/* Compares the supplied certificate with the certificate
64305 * in the endpoint context
64306 */
64307
64308static UA_StatusCode
64309UA_Asy_Basic256_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
64310 const UA_ByteString * certificateThumbprint) {
64311 if (securityPolicy == NULL || certificateThumbprint == NULL) {
64312 return UA_STATUSCODE_BADINVALIDARGUMENT;
64313 }
64314 Policy_Context_Basic256 *pc = (Policy_Context_Basic256 *)
64315 securityPolicy->policyContext;
64316 if(!UA_ByteString_equal(string1: certificateThumbprint, string2: &pc->localCertThumbprint)) {
64317 return UA_STATUSCODE_BADCERTIFICATEINVALID;
64318 }
64319 return UA_STATUSCODE_GOOD;
64320}
64321
64322/* Generates a thumbprint for the specified certificate */
64323
64324static UA_StatusCode
64325UA_Asy_Basic256_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
64326 const UA_ByteString * certificate,
64327 UA_ByteString * thumbprint) {
64328 return UA_Openssl_X509_GetCertificateThumbprint (certficate: certificate,
64329 pThumbprint: thumbprint, false);
64330}
64331
64332static UA_StatusCode
64333UA_ChannelModule_Basic256_setLocalSymSigningKey (void * channelContext,
64334 const UA_ByteString * key) {
64335 if (key == NULL || channelContext == NULL) {
64336 return UA_STATUSCODE_BADINVALIDARGUMENT;
64337 }
64338
64339 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64340 UA_ByteString_clear(p: &cc->localSymSigningKey);
64341 return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey);
64342}
64343
64344static UA_StatusCode
64345UA_ChannelModule_Basic256_setLocalSymEncryptingKey (void * channelContext,
64346 const UA_ByteString * key) {
64347 if (key == NULL || channelContext == NULL) {
64348 return UA_STATUSCODE_BADINVALIDARGUMENT;
64349 }
64350
64351 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64352 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
64353 return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey);
64354}
64355
64356static UA_StatusCode
64357UA_ChannelModule_Basic256_setLocalSymIv (void * channelContext,
64358 const UA_ByteString * iv) {
64359 if (iv == NULL || channelContext == NULL) {
64360 return UA_STATUSCODE_BADINVALIDARGUMENT;
64361 }
64362
64363 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64364 UA_ByteString_clear(p: &cc->localSymIv);
64365 return UA_ByteString_copy(src: iv, dst: &cc->localSymIv);
64366}
64367
64368static UA_StatusCode
64369UA_ChannelModule_Basic256_setRemoteSymSigningKey (void * channelContext,
64370 const UA_ByteString * key) {
64371 if (key == NULL || channelContext == NULL) {
64372 return UA_STATUSCODE_BADINVALIDARGUMENT;
64373 }
64374
64375 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64376 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
64377 return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey);
64378}
64379
64380static UA_StatusCode
64381UA_ChannelModule_Basic256_setRemoteSymEncryptingKey (void * channelContext,
64382 const UA_ByteString * key) {
64383 if (key == NULL || channelContext == NULL) {
64384 return UA_STATUSCODE_BADINVALIDARGUMENT;
64385 }
64386
64387 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64388 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
64389 return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey);
64390}
64391
64392static UA_StatusCode
64393UA_ChannelModule_Basic256_setRemoteSymIv (void * channelContext,
64394 const UA_ByteString * key) {
64395 if (key == NULL || channelContext == NULL) {
64396 return UA_STATUSCODE_BADINVALIDARGUMENT;
64397 }
64398
64399 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64400 UA_ByteString_clear(p: &cc->remoteSymIv);
64401 return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv);
64402}
64403
64404static UA_StatusCode
64405UA_ChannelModule_Basic256_compareCertificate (const void * channelContext,
64406 const UA_ByteString * certificate) {
64407 if(channelContext == NULL || certificate == NULL) {
64408 return UA_STATUSCODE_BADINVALIDARGUMENT;
64409 }
64410
64411 const Channel_Context_Basic256 * cc =
64412 (const Channel_Context_Basic256 *) channelContext;
64413 return UA_OpenSSL_X509_compare (cert: certificate, bcert: cc->remoteCertificateX509);
64414}
64415
64416static size_t
64417UA_AsySig_Basic256_getRemoteSignatureSize (const void *channelContext) {
64418 if (channelContext == NULL) {
64419 return UA_STATUSCODE_BADINVALIDARGUMENT;
64420 }
64421
64422 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64423 UA_Int32 keyLen = 0;
64424 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64425 return (size_t) keyLen;
64426}
64427
64428static size_t
64429UA_AsySig_Basic256_getLocalSignatureSize (const void *channelContext) {
64430 if (channelContext == NULL) {
64431 return UA_STATUSCODE_BADINVALIDARGUMENT;
64432 }
64433
64434 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64435 Policy_Context_Basic256 * pc = cc->policyContext;
64436 UA_Int32 keyLen = 0;
64437 UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen);
64438
64439 return (size_t) keyLen;
64440}
64441
64442static UA_StatusCode
64443UA_AsySig_Basic256_Verify (void * channelContext,
64444 const UA_ByteString * message,
64445 const UA_ByteString * signature) {
64446 if (message == NULL || signature == NULL || channelContext == NULL) {
64447 return UA_STATUSCODE_BADINVALIDARGUMENT;
64448 }
64449
64450 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64451 UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (msg: message,
64452 publicKeyX509: cc->remoteCertificateX509, signature);
64453 return retval;
64454}
64455
64456static UA_StatusCode
64457UA_AsySig_Basic256_Sign (void * channelContext,
64458 const UA_ByteString * message,
64459 UA_ByteString * signature) {
64460 if (channelContext == NULL || message == NULL || signature == NULL) {
64461 return UA_STATUSCODE_BADINVALIDARGUMENT;
64462 }
64463
64464 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64465 Policy_Context_Basic256 * pc = cc->policyContext;
64466 return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, privateKey: pc->localPrivateKey,
64467 outSignature: signature);
64468}
64469
64470static size_t
64471UA_AsymEn_Basic256_getRemotePlainTextBlockSize (const void *channelContext) {
64472 if (channelContext == NULL) {
64473 return UA_STATUSCODE_BADINVALIDARGUMENT;
64474 }
64475
64476 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64477 UA_Int32 keyLen = 0;
64478 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64479 return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
64480}
64481
64482static size_t
64483UA_AsymEn_Basic256_getRemoteBlockSize (const void *channelContext) {
64484 if (channelContext == NULL) {
64485 return UA_STATUSCODE_BADINVALIDARGUMENT;
64486 }
64487
64488 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64489 UA_Int32 keyLen = 0;
64490 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64491 return (size_t) keyLen;
64492}
64493
64494static size_t
64495UA_AsymEn_Basic256_getRemoteKeyLength (const void *channelContext) {
64496 if (channelContext == NULL)
64497 return UA_STATUSCODE_BADINVALIDARGUMENT;
64498
64499 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64500 UA_Int32 keyLen = 0;
64501 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64502 return (size_t) keyLen * 8;
64503}
64504
64505static size_t
64506UA_AsymEn_Basic256_getLocalKeyLength (const void *channelContext) {
64507 if (channelContext == NULL)
64508 return UA_STATUSCODE_BADINVALIDARGUMENT;
64509
64510 const Channel_Context_Basic256 *cc = (const Channel_Context_Basic256 *) channelContext;
64511 Policy_Context_Basic256 *pc = cc->policyContext;
64512 UA_Int32 keyLen = 0;
64513 UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen);
64514
64515 return (size_t) keyLen * 8;
64516}
64517
64518static UA_StatusCode
64519UA_AsymEn_Basic256_Decrypt (void * channelContext,
64520 UA_ByteString * data) {
64521 if (channelContext == NULL || data == NULL) {
64522 return UA_STATUSCODE_BADINVALIDARGUMENT;
64523 }
64524
64525 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64526 UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt (data,
64527 privateKey: cc->policyContext->localPrivateKey);
64528 return ret;
64529}
64530
64531static UA_StatusCode
64532UA_AsymEn_Basic256_Encrypt (void * channelContext,
64533 UA_ByteString * data) {
64534 if (channelContext == NULL || data == NULL) {
64535 return UA_STATUSCODE_BADINVALIDARGUMENT;
64536 }
64537
64538 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64539 return UA_Openssl_RSA_OAEP_Encrypt (data, UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN,
64540 publicX509: cc->remoteCertificateX509);
64541}
64542
64543static UA_StatusCode
64544UA_Sym_Basic256_generateNonce(void *policyContext,
64545 UA_ByteString *out) {
64546 UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length);
64547 if (rc != 1) {
64548 return UA_STATUSCODE_BADUNEXPECTEDERROR;
64549 }
64550 return UA_STATUSCODE_GOOD;
64551}
64552
64553static UA_StatusCode
64554UA_Sym_Basic256_generateKey(void *policyContext, const UA_ByteString *secret,
64555 const UA_ByteString *seed, UA_ByteString *out) {
64556 return UA_Openssl_Random_Key_PSHA1_Derive(secret, seed, out);
64557}
64558
64559static size_t
64560UA_SymEn_Basic256_getLocalKeyLength (const void * channelContext) {
64561 /* 32 bytes 256 bits */
64562 return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH;
64563}
64564
64565static size_t
64566UA_SymEn_Basic256_getBlockSize (const void * channelContext) {
64567 return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
64568}
64569
64570static size_t
64571UA_SymEn_Basic256_getRemoteKeyLength (const void * channelContext) {
64572 /* 32 bytes 256 bits */
64573 return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH;
64574}
64575
64576static UA_StatusCode
64577UA_SymEn_Basic256_Encrypt (void * channelContext,
64578 UA_ByteString * data) {
64579 if(channelContext == NULL || data == NULL)
64580 return UA_STATUSCODE_BADINVALIDARGUMENT;
64581
64582 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64583 return UA_OpenSSL_AES_256_CBC_Encrypt (iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data);
64584}
64585
64586static UA_StatusCode
64587UA_SymEn_Basic256_Decrypt (void * channelContext,
64588 UA_ByteString * data) {
64589 if(channelContext == NULL || data == NULL)
64590 return UA_STATUSCODE_BADINVALIDARGUMENT;
64591 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64592 return UA_OpenSSL_AES_256_CBC_Decrypt (iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey, data);
64593}
64594
64595static size_t
64596UA_SymSig_Basic256_getKeyLength (const void * channelContext) {
64597 return UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH;
64598}
64599
64600static size_t
64601UA_SymSig_Basic256_getSignatureSize (const void * channelContext) {
64602 return UA_SHA1_LENGTH;
64603}
64604
64605static UA_StatusCode
64606UA_SymSig_Basic256_Verify (void * channelContext,
64607 const UA_ByteString * message,
64608 const UA_ByteString * signature) {
64609 if (channelContext == NULL ||
64610 message == NULL || signature == NULL)
64611 return UA_STATUSCODE_BADINVALIDARGUMENT;
64612
64613 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64614 return UA_OpenSSL_HMAC_SHA1_Verify (message,
64615 key: &cc->remoteSymSigningKey,
64616 signature);
64617}
64618
64619static UA_StatusCode
64620UA_SymSig_Basic256_Sign (void * channelContext,
64621 const UA_ByteString * message,
64622 UA_ByteString * signature) {
64623 if (channelContext == NULL || message == NULL || signature == NULL)
64624 return UA_STATUSCODE_BADINVALIDARGUMENT;
64625
64626 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64627 return UA_OpenSSL_HMAC_SHA1_Sign (message, key: &cc->localSymSigningKey, signature);
64628}
64629
64630/* the main entry of Basic256 */
64631
64632UA_StatusCode
64633UA_SecurityPolicy_Basic256 (UA_SecurityPolicy * policy,
64634 const UA_ByteString localCertificate,
64635 const UA_ByteString localPrivateKey,
64636 const UA_Logger * logger) {
64637 UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
64638 UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
64639 UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
64640 UA_StatusCode retval;
64641
64642 UA_LOG_INFO (logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
64643 msg: "The basic256 security policy with openssl is added.");
64644
64645 UA_Openssl_Init ();
64646 memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy));
64647 policy->logger = logger;
64648 policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256\0");
64649
64650 /* set ChannelModule context */
64651
64652 channelModule->newContext = UA_ChannelModule_Basic256_New_Context;
64653 channelModule->deleteContext = UA_ChannelModule_Basic256_Delete_Context;
64654
64655 channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic256_setLocalSymSigningKey;
64656 channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic256_setLocalSymEncryptingKey;
64657 channelModule->setLocalSymIv = UA_ChannelModule_Basic256_setLocalSymIv;
64658 channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic256_setRemoteSymSigningKey;
64659 channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic256_setRemoteSymEncryptingKey;
64660 channelModule->setRemoteSymIv = UA_ChannelModule_Basic256_setRemoteSymIv;
64661 channelModule->compareCertificate = UA_ChannelModule_Basic256_compareCertificate;
64662
64663 retval = UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate);
64664
64665 if (retval != UA_STATUSCODE_GOOD)
64666 return retval;
64667
64668 /* asymmetricModule */
64669
64670 asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic256_compareCertificateThumbprint;
64671 asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic256_makeCertificateThumbprint;
64672
64673 /* AsymmetricModule - signature algorithm */
64674
64675 UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
64676 &asymmetricModule->cryptoModule.signatureAlgorithm;
64677 asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
64678 asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic256_getRemoteSignatureSize;
64679 asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256_getLocalSignatureSize;
64680 asySigAlgorithm->verify = UA_AsySig_Basic256_Verify;
64681 asySigAlgorithm->sign = UA_AsySig_Basic256_Sign;
64682 asySigAlgorithm->getLocalKeyLength = NULL;
64683 asySigAlgorithm->getRemoteKeyLength = NULL;
64684
64685 /* AsymmetricModule encryption algorithm */
64686
64687 UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
64688 &asymmetricModule->cryptoModule.encryptionAlgorithm;
64689 asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
64690 asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic256_getRemotePlainTextBlockSize;
64691 asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256_getRemoteBlockSize;
64692 asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256_getRemoteKeyLength;
64693 asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256_getLocalKeyLength;
64694 asymEncryAlg->decrypt = UA_AsymEn_Basic256_Decrypt;
64695 asymEncryAlg->encrypt = UA_AsymEn_Basic256_Encrypt;
64696
64697 /* SymmetricModule */
64698
64699 symmetricModule->secureChannelNonceLength = 32;
64700 symmetricModule->generateNonce = UA_Sym_Basic256_generateNonce;
64701 symmetricModule->generateKey = UA_Sym_Basic256_generateKey;
64702
64703 /* Symmetric encryption Algorithm */
64704
64705 UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
64706 &symmetricModule->cryptoModule.encryptionAlgorithm;
64707 symEncryptionAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
64708 symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256_getLocalKeyLength;
64709 symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256_getRemoteKeyLength;
64710 symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256_getBlockSize;
64711 symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256_getBlockSize;
64712 symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256_Decrypt;
64713 symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256_Encrypt;
64714
64715 /* Symmetric signature Algorithm */
64716
64717 UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
64718 &symmetricModule->cryptoModule.signatureAlgorithm;
64719 symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
64720 symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic256_getKeyLength;
64721 symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic256_getKeyLength;
64722 symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic256_getSignatureSize;
64723 symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic256_getSignatureSize;
64724 symSignatureAlgorithm->verify = UA_SymSig_Basic256_Verify;
64725 symSignatureAlgorithm->sign = UA_SymSig_Basic256_Sign;
64726
64727 /* set the policy context */
64728
64729 retval = UA_Policy_Basic256_New_Context (securityPolicy: policy, localPrivateKey, logger);
64730 if (retval != UA_STATUSCODE_GOOD) {
64731 UA_ByteString_clear (p: &policy->localCertificate);
64732 return retval;
64733 }
64734 policy->clear = UA_Policy_Basic256_Clear_Context;
64735
64736 /* Use the same signature algorithm as the asymmetric component for
64737 certificate signing (see standard) */
64738 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
64739
64740 return UA_STATUSCODE_GOOD;
64741}
64742
64743#endif
64744
64745/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic256sha256.c" ****/
64746
64747/* This Source Code Form is subject to the terms of the Mozilla Public
64748 * License, v. 2.0. If a copy of the MPL was not distributed with this
64749 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
64750 *
64751 * Copyright 2020 (c) Wind River Systems, Inc.
64752 * Copyright 2020 (c) basysKom GmbH
64753 */
64754
64755
64756#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
64757
64758
64759#include <openssl/hmac.h>
64760#include <openssl/sha.h>
64761#include <openssl/rsa.h>
64762#include <openssl/x509.h>
64763#include <openssl/rand.h>
64764#include <openssl/rsa.h>
64765
64766#define UA_SHA256_LENGTH 32 /* 256 bit */
64767#define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42
64768#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32
64769#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH 32
64770#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE 16
64771#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
64772#define UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH 256
64773#define UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH 512
64774
64775typedef struct {
64776 EVP_PKEY *localPrivateKey;
64777 UA_ByteString localCertThumbprint;
64778 const UA_Logger *logger;
64779} Policy_Context_Basic256Sha256;
64780
64781typedef struct {
64782 UA_ByteString localSymSigningKey;
64783 UA_ByteString localSymEncryptingKey;
64784 UA_ByteString localSymIv;
64785 UA_ByteString remoteSymSigningKey;
64786 UA_ByteString remoteSymEncryptingKey;
64787 UA_ByteString remoteSymIv;
64788
64789 Policy_Context_Basic256Sha256 *policyContext;
64790 UA_ByteString remoteCertificate;
64791 X509 *remoteCertificateX509; /* X509 */
64792} Channel_Context_Basic256Sha256;
64793
64794/* create the policy context */
64795
64796static UA_StatusCode
64797UA_Policy_New_Context(UA_SecurityPolicy * securityPolicy,
64798 const UA_ByteString localPrivateKey,
64799 const UA_Logger *logger) {
64800 Policy_Context_Basic256Sha256 *context = (Policy_Context_Basic256Sha256 *)
64801 UA_malloc(size: sizeof(Policy_Context_Basic256Sha256));
64802 if(context == NULL)
64803 return UA_STATUSCODE_BADOUTOFMEMORY;
64804 context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey);
64805
64806 if(!context->localPrivateKey) {
64807 UA_free(ptr: context);
64808 return UA_STATUSCODE_BADINVALIDARGUMENT;
64809 }
64810
64811 UA_StatusCode retval =
64812 UA_Openssl_X509_GetCertificateThumbprint(certficate: &securityPolicy->localCertificate,
64813 pThumbprint: &context->localCertThumbprint, true);
64814 if(retval != UA_STATUSCODE_GOOD) {
64815 EVP_PKEY_free(pkey: context->localPrivateKey);
64816 UA_free(ptr: context);
64817 return retval;
64818 }
64819
64820 context->logger = logger;
64821 securityPolicy->policyContext = context;
64822 return UA_STATUSCODE_GOOD;
64823}
64824
64825/* Clear the policy context */
64826static void
64827UA_Policy_Clear_Context(UA_SecurityPolicy *policy) {
64828 if(policy == NULL)
64829 return;
64830
64831 UA_ByteString_clear(p: &policy->localCertificate);
64832
64833 /* Delete all allocated members in the context */
64834 Policy_Context_Basic256Sha256 *pc =
64835 (Policy_Context_Basic256Sha256 *) policy->policyContext;
64836 EVP_PKEY_free(pkey: pc->localPrivateKey);
64837 UA_ByteString_clear(p: &pc->localCertThumbprint);
64838 UA_free(ptr: pc);
64839 return;
64840}
64841
64842/* create the channel context */
64843
64844static UA_StatusCode
64845UA_ChannelModule_New_Context(const UA_SecurityPolicy * securityPolicy,
64846 const UA_ByteString * remoteCertificate,
64847 void ** channelContext) {
64848 if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL)
64849 return UA_STATUSCODE_BADINTERNALERROR;
64850
64851 Channel_Context_Basic256Sha256 *context = (Channel_Context_Basic256Sha256 *)
64852 UA_malloc(size: sizeof(Channel_Context_Basic256Sha256));
64853 if(context == NULL)
64854 return UA_STATUSCODE_BADOUTOFMEMORY;
64855
64856 UA_ByteString_init(p: &context->localSymSigningKey);
64857 UA_ByteString_init(p: &context->localSymEncryptingKey);
64858 UA_ByteString_init(p: &context->localSymIv);
64859 UA_ByteString_init(p: &context->remoteSymSigningKey);
64860 UA_ByteString_init(p: &context->remoteSymEncryptingKey);
64861 UA_ByteString_init(p: &context->remoteSymIv);
64862
64863 UA_StatusCode retval =
64864 UA_copyCertificate(dst: &context->remoteCertificate, src: remoteCertificate);
64865 if(retval != UA_STATUSCODE_GOOD) {
64866 UA_free(ptr: context);
64867 return retval;
64868 }
64869
64870 /* decode to X509 */
64871 context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate);
64872 if(context->remoteCertificateX509 == NULL) {
64873 UA_ByteString_clear(p: &context->remoteCertificate);
64874 UA_free(ptr: context);
64875 }
64876
64877 context->policyContext =
64878 (Policy_Context_Basic256Sha256 *)securityPolicy->policyContext;
64879 *channelContext = context;
64880
64881 UA_LOG_INFO(logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
64882 msg: "The basic256sha256 security policy channel with openssl is created.");
64883
64884 return UA_STATUSCODE_GOOD;
64885}
64886
64887/* delete the channel context */
64888
64889static void
64890UA_ChannelModule_Delete_Context(void * channelContext) {
64891 if(!channelContext)
64892 return;
64893
64894 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *)channelContext;
64895 X509_free(a: cc->remoteCertificateX509);
64896 UA_ByteString_clear(p: &cc->remoteCertificate);
64897 UA_ByteString_clear(p: &cc->localSymSigningKey);
64898 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
64899 UA_ByteString_clear(p: &cc->localSymIv);
64900 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
64901 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
64902 UA_ByteString_clear(p: &cc->remoteSymIv);
64903
64904 UA_LOG_INFO(logger: cc->policyContext->logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
64905 msg: "The basic256sha256 security policy channel with openssl is deleted.");
64906 UA_free(ptr: cc);
64907}
64908
64909/* Verifies the signature of the message using the provided keys in the context.
64910 * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
64911static UA_StatusCode
64912UA_AsySig_Basic256Sha256_Verify(void *channelContext,
64913 const UA_ByteString *message,
64914 const UA_ByteString *signature) {
64915 if(message == NULL || signature == NULL || channelContext == NULL)
64916 return UA_STATUSCODE_BADINTERNALERROR;
64917
64918 Channel_Context_Basic256Sha256 * cc =
64919 (Channel_Context_Basic256Sha256 *) channelContext;
64920 return UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(msg: message, publicKeyX509: cc->remoteCertificateX509,
64921 signature);
64922}
64923
64924/* Compares the supplied certificate with the certificate
64925 * in the endpoint context
64926 */
64927
64928static UA_StatusCode
64929UA_compareCertificateThumbprint(const UA_SecurityPolicy * securityPolicy,
64930 const UA_ByteString * certificateThumbprint) {
64931 if(securityPolicy == NULL || certificateThumbprint == NULL)
64932 return UA_STATUSCODE_BADINVALIDARGUMENT;
64933 Policy_Context_Basic256Sha256 *pc = (Policy_Context_Basic256Sha256 *)
64934 securityPolicy->policyContext;
64935 if(!UA_ByteString_equal(string1: certificateThumbprint, string2: &pc->localCertThumbprint))
64936 return UA_STATUSCODE_BADCERTIFICATEINVALID;
64937 return UA_STATUSCODE_GOOD;
64938}
64939
64940/* Generates a thumbprint for the specified certificate */
64941
64942static UA_StatusCode
64943UA_makeCertificateThumbprint(const UA_SecurityPolicy * securityPolicy,
64944 const UA_ByteString * certificate,
64945 UA_ByteString * thumbprint) {
64946 return UA_Openssl_X509_GetCertificateThumbprint(certficate: certificate, pThumbprint: thumbprint, false);
64947}
64948
64949static UA_StatusCode
64950UA_Asym_Basic256Sha256_Decrypt(void * channelContext, UA_ByteString * data) {
64951 if(channelContext == NULL || data == NULL)
64952 return UA_STATUSCODE_BADINVALIDARGUMENT;
64953
64954 Channel_Context_Basic256Sha256 * cc =
64955 (Channel_Context_Basic256Sha256 *) channelContext;
64956 return UA_Openssl_RSA_Oaep_Decrypt(data, privateKey: cc->policyContext->localPrivateKey);
64957}
64958
64959static size_t
64960UA_Asym_Basic256Sha256_getRemoteSignatureSize(const void *channelContext) {
64961 if(channelContext == NULL)
64962 return UA_STATUSCODE_BADINTERNALERROR;
64963
64964 const Channel_Context_Basic256Sha256 * cc =
64965 (const Channel_Context_Basic256Sha256 *) channelContext;
64966 UA_Int32 keyLen = 0;
64967 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64968 return (size_t) keyLen;
64969}
64970
64971static size_t
64972UA_AsySig_Basic256Sha256_getLocalSignatureSize(const void *channelContext) {
64973 if(channelContext == NULL)
64974 return UA_STATUSCODE_BADINTERNALERROR;
64975
64976 const Channel_Context_Basic256Sha256 *cc =
64977 (const Channel_Context_Basic256Sha256 *) channelContext;
64978 Policy_Context_Basic256Sha256 * pc = cc->policyContext;
64979 UA_Int32 keyLen = 0;
64980 UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen);
64981 return (size_t) keyLen;
64982}
64983
64984static size_t
64985UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize(const void *channelContext) {
64986 if(channelContext == NULL)
64987 return UA_STATUSCODE_BADINTERNALERROR;
64988
64989 const Channel_Context_Basic256Sha256 *cc =
64990 (const Channel_Context_Basic256Sha256 *) channelContext;
64991 UA_Int32 keyLen = 0;
64992 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64993 return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
64994}
64995
64996static size_t
64997UA_AsymEn_Basic256Sha256_getRemoteBlockSize(const void *channelContext) {
64998 if(channelContext == NULL)
64999 return UA_STATUSCODE_BADINTERNALERROR;
65000
65001 const Channel_Context_Basic256Sha256 * cc =
65002 (const Channel_Context_Basic256Sha256 *) channelContext;
65003 UA_Int32 keyLen = 0;
65004 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65005 return (size_t) keyLen;
65006}
65007
65008static size_t
65009UA_AsymEn_Basic256Sha256_getRemoteKeyLength(const void *channelContext) {
65010 if(channelContext == NULL)
65011 return UA_STATUSCODE_BADINTERNALERROR;
65012
65013 const Channel_Context_Basic256Sha256 *cc =
65014 (const Channel_Context_Basic256Sha256 *) channelContext;
65015 UA_Int32 keyLen = 0;
65016 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65017 return (size_t) keyLen * 8;
65018}
65019
65020static UA_StatusCode
65021UA_Sym_Basic256Sha256_generateNonce(void *policyContext,
65022 UA_ByteString *out) {
65023 UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length);
65024 if(rc != 1)
65025 return UA_STATUSCODE_BADUNEXPECTEDERROR;
65026 return UA_STATUSCODE_GOOD;
65027}
65028
65029static size_t
65030UA_SymEn_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
65031 /* 32 bytes 256 bits */
65032 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH;
65033}
65034
65035static size_t
65036UA_SymSig_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
65037 /* 32 bytes 256 bits */
65038 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
65039}
65040
65041static UA_StatusCode
65042UA_Sym_Basic256Sha256_generateKey(void *policyContext,
65043 const UA_ByteString *secret,
65044 const UA_ByteString *seed,
65045 UA_ByteString *out) {
65046 return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out);
65047}
65048
65049static UA_StatusCode
65050UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey(void * channelContext,
65051 const UA_ByteString * key) {
65052 if(key == NULL || channelContext == NULL)
65053 return UA_STATUSCODE_BADINTERNALERROR;
65054 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65055 UA_ByteString_clear(p: &cc->localSymSigningKey);
65056 return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey);
65057}
65058
65059static UA_StatusCode
65060UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey(void * channelContext,
65061 const UA_ByteString * key) {
65062 if(key == NULL || channelContext == NULL)
65063 return UA_STATUSCODE_BADINTERNALERROR;
65064 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65065 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
65066 return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey);
65067}
65068
65069static UA_StatusCode
65070UA_ChannelM_Basic256Sha256_setLocalSymIv(void * channelContext,
65071 const UA_ByteString * iv) {
65072 if(iv == NULL || channelContext == NULL)
65073 return UA_STATUSCODE_BADINTERNALERROR;
65074 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65075 UA_ByteString_clear(p: &cc->localSymIv);
65076 return UA_ByteString_copy(src: iv, dst: &cc->localSymIv);
65077}
65078
65079static size_t
65080UA_SymEn_Basic256Sha256_getRemoteKeyLength(const void * channelContext) {
65081 /* 32 bytes 256 bits */
65082 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH;
65083}
65084
65085static size_t
65086UA_SymEn_Basic256Sha256_getBlockSize(const void *channelContext) {
65087 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
65088}
65089
65090static size_t
65091UA_SymSig_Basic256Sha256_getRemoteKeyLength(const void * channelContext) {
65092 /* 32 bytes 256 bits */
65093 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
65094}
65095
65096static UA_StatusCode
65097UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey(void *channelContext,
65098 const UA_ByteString * key) {
65099 if(key == NULL || channelContext == NULL)
65100 return UA_STATUSCODE_BADINTERNALERROR;
65101 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65102 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
65103 return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey);
65104}
65105
65106static UA_StatusCode
65107UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey(void *channelContext,
65108 const UA_ByteString * key) {
65109 if(key == NULL || channelContext == NULL)
65110 return UA_STATUSCODE_BADINTERNALERROR;
65111 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65112 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
65113 return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey);
65114}
65115
65116static UA_StatusCode
65117UA_ChannelM_Basic256Sha256_setRemoteSymIv(void *channelContext,
65118 const UA_ByteString * key) {
65119 if(key == NULL || channelContext == NULL)
65120 return UA_STATUSCODE_BADINTERNALERROR;
65121 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65122 UA_ByteString_clear(p: &cc->remoteSymIv);
65123 return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv);
65124}
65125
65126static UA_StatusCode
65127UA_AsySig_Basic256Sha256_sign(void *channelContext, const UA_ByteString * message,
65128 UA_ByteString *signature) {
65129 if(channelContext == NULL || message == NULL || signature == NULL)
65130 return UA_STATUSCODE_BADINTERNALERROR;
65131 Channel_Context_Basic256Sha256 *cc = (Channel_Context_Basic256Sha256 *) channelContext;
65132 Policy_Context_Basic256Sha256 *pc = cc->policyContext;
65133 return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, privateKey: pc->localPrivateKey, outSignature: signature);
65134}
65135
65136static UA_StatusCode
65137UA_AsymEn_Basic256Sha256_encrypt(void *channelContext, UA_ByteString *data) {
65138 if(channelContext == NULL || data == NULL)
65139 return UA_STATUSCODE_BADINTERNALERROR;
65140 Channel_Context_Basic256Sha256 * cc =
65141 (Channel_Context_Basic256Sha256 *) channelContext;
65142 return UA_Openssl_RSA_OAEP_Encrypt(data, UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN,
65143 publicX509: cc->remoteCertificateX509);
65144}
65145
65146static size_t
65147UA_SymSig_Basic256Sha256_getRemoteSignatureSize(const void *channelContext) {
65148 return UA_SHA256_LENGTH;
65149}
65150
65151static UA_StatusCode
65152UA_SymSig_Basic256Sha256_verify(void *channelContext, const UA_ByteString *message,
65153 const UA_ByteString *signature) {
65154 if(channelContext == NULL || message == NULL || signature == NULL)
65155 return UA_STATUSCODE_BADINTERNALERROR;
65156
65157 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65158 return UA_OpenSSL_HMAC_SHA256_Verify(message, key: &cc->remoteSymSigningKey, signature);
65159}
65160
65161static UA_StatusCode
65162UA_SymSig_Basic256Sha256_sign(void *channelContext, const UA_ByteString *message,
65163 UA_ByteString *signature) {
65164 if(channelContext == NULL || message == NULL || signature == NULL)
65165 return UA_STATUSCODE_BADINTERNALERROR;
65166
65167 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65168 return UA_OpenSSL_HMAC_SHA256_Sign(message, key: &cc->localSymSigningKey, signature);
65169}
65170
65171static size_t
65172UA_SymSig_Basic256Sha256_getLocalSignatureSize(const void * channelContext) {
65173 return UA_SHA256_LENGTH;
65174}
65175
65176static UA_StatusCode
65177UA_SymEn_Basic256Sha256_decrypt(void *channelContext, UA_ByteString *data) {
65178 if(channelContext == NULL || data == NULL)
65179 return UA_STATUSCODE_BADINTERNALERROR;
65180 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65181 return UA_OpenSSL_AES_256_CBC_Decrypt(iv: &cc->remoteSymIv,
65182 key: &cc->remoteSymEncryptingKey, data);
65183}
65184
65185static UA_StatusCode
65186UA_SymEn_Basic256Sha256_encrypt(void *channelContext, UA_ByteString *data) {
65187 if(channelContext == NULL || data == NULL)
65188 return UA_STATUSCODE_BADINTERNALERROR;
65189
65190 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65191 return UA_OpenSSL_AES_256_CBC_Encrypt(iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data);
65192}
65193
65194static UA_StatusCode
65195UA_ChannelM_Basic256Sha256_compareCertificate(const void *channelContext,
65196 const UA_ByteString *certificate) {
65197 if(channelContext == NULL || certificate == NULL)
65198 return UA_STATUSCODE_BADINTERNALERROR;
65199
65200 const Channel_Context_Basic256Sha256 * cc =
65201 (const Channel_Context_Basic256Sha256 *) channelContext;
65202 return UA_OpenSSL_X509_compare(cert: certificate, bcert: cc->remoteCertificateX509);
65203}
65204
65205static size_t
65206UA_AsymEn_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
65207 if(channelContext == NULL)
65208 return UA_STATUSCODE_BADINTERNALERROR;
65209
65210 const Channel_Context_Basic256Sha256 * cc =
65211 (const Channel_Context_Basic256Sha256 *) channelContext;
65212 Policy_Context_Basic256Sha256 *pc = cc->policyContext;
65213 UA_Int32 keyLen = 0;
65214 UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen);
65215 return (size_t) keyLen * 8;
65216}
65217
65218/* the main entry of Basic256Sha256 */
65219
65220UA_StatusCode
65221UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy,
65222 const UA_ByteString localCertificate,
65223 const UA_ByteString localPrivateKey,
65224 const UA_Logger *logger) {
65225 UA_SecurityPolicyAsymmetricModule *asymmetricModule = &policy->asymmetricModule;
65226 UA_SecurityPolicySymmetricModule *symmetricModule = &policy->symmetricModule;
65227 UA_SecurityPolicyChannelModule *channelModule = &policy->channelModule;
65228 UA_LOG_INFO(logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65229 msg: "The basic256sha256 security policy with openssl is added.");
65230
65231 UA_Openssl_Init();
65232 memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy));
65233 policy->logger = logger;
65234 policy->policyUri =
65235 UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256\0");
65236
65237 /* Set ChannelModule context */
65238 channelModule->newContext = UA_ChannelModule_New_Context;
65239 channelModule->deleteContext = UA_ChannelModule_Delete_Context;
65240 channelModule->setLocalSymSigningKey =
65241 UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey;
65242 channelModule->setLocalSymEncryptingKey =
65243 UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey;
65244 channelModule->setLocalSymIv = UA_ChannelM_Basic256Sha256_setLocalSymIv;
65245 channelModule->setRemoteSymSigningKey =
65246 UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey;
65247 channelModule->setRemoteSymEncryptingKey =
65248 UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey;
65249 channelModule->setRemoteSymIv = UA_ChannelM_Basic256Sha256_setRemoteSymIv;
65250 channelModule->compareCertificate = UA_ChannelM_Basic256Sha256_compareCertificate;
65251 UA_StatusCode retval =
65252 UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate);
65253 if(retval != UA_STATUSCODE_GOOD)
65254 return retval;
65255
65256 /* AsymmetricModule - signature algorithm */
65257 UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm =
65258 &asymmetricModule->cryptoModule.signatureAlgorithm;
65259 asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
65260 asySigAlgorithm->verify = UA_AsySig_Basic256Sha256_Verify;
65261 asySigAlgorithm->sign = UA_AsySig_Basic256Sha256_sign;
65262 asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256Sha256_getLocalSignatureSize;
65263 asySigAlgorithm->getRemoteSignatureSize = UA_Asym_Basic256Sha256_getRemoteSignatureSize;
65264 asySigAlgorithm->getLocalKeyLength = NULL;
65265 asySigAlgorithm->getRemoteKeyLength = NULL;
65266
65267 /* AsymmetricModule encryption algorithm */
65268 UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg =
65269 &asymmetricModule->cryptoModule.encryptionAlgorithm;
65270 asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
65271 asymEncryAlg->encrypt = UA_AsymEn_Basic256Sha256_encrypt;
65272 asymEncryAlg->decrypt = UA_Asym_Basic256Sha256_Decrypt;
65273 asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256Sha256_getLocalKeyLength;
65274 asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256Sha256_getRemoteKeyLength;
65275 asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256Sha256_getRemoteBlockSize;
65276 asymEncryAlg->getRemotePlainTextBlockSize =
65277 UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize;
65278
65279 /* AsymmetricModule */
65280 asymmetricModule->compareCertificateThumbprint = UA_compareCertificateThumbprint;
65281 asymmetricModule->makeCertificateThumbprint = UA_makeCertificateThumbprint;
65282
65283 /* SymmetricModule */
65284 symmetricModule->secureChannelNonceLength = 32;
65285 symmetricModule->generateNonce = UA_Sym_Basic256Sha256_generateNonce;
65286 symmetricModule->generateKey = UA_Sym_Basic256Sha256_generateKey;
65287
65288 /* Symmetric encryption Algorithm */
65289 UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm =
65290 &symmetricModule->cryptoModule.encryptionAlgorithm;
65291 symEncryptionAlgorithm->uri =
65292 UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
65293 symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256Sha256_encrypt;
65294 symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256Sha256_decrypt;
65295 symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256Sha256_getLocalKeyLength;
65296 symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256Sha256_getRemoteKeyLength;
65297 symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256Sha256_getBlockSize;
65298 symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256Sha256_getBlockSize;
65299
65300 /* Symmetric signature Algorithm */
65301 UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm =
65302 &symmetricModule->cryptoModule.signatureAlgorithm;
65303 symSignatureAlgorithm->uri =
65304 UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0");
65305 symSignatureAlgorithm->verify = UA_SymSig_Basic256Sha256_verify;
65306 symSignatureAlgorithm->sign = UA_SymSig_Basic256Sha256_sign;
65307 symSignatureAlgorithm->getLocalSignatureSize =
65308 UA_SymSig_Basic256Sha256_getLocalSignatureSize;
65309 symSignatureAlgorithm->getRemoteSignatureSize =
65310 UA_SymSig_Basic256Sha256_getRemoteSignatureSize;
65311 symSignatureAlgorithm->getLocalKeyLength =
65312 UA_SymSig_Basic256Sha256_getLocalKeyLength;
65313 symSignatureAlgorithm->getRemoteKeyLength =
65314 UA_SymSig_Basic256Sha256_getRemoteKeyLength;
65315
65316 policy->clear = UA_Policy_Clear_Context;
65317 retval = UA_Policy_New_Context(securityPolicy: policy, localPrivateKey, logger);
65318 if(retval != UA_STATUSCODE_GOOD) {
65319 UA_ByteString_clear(p: &policy->localCertificate);
65320 return retval;
65321 }
65322
65323 /* Use the same signature algorithm as the asymmetric component for
65324 * certificate signing (see standard) */
65325 policy->certificateSigningAlgorithm =
65326 policy->asymmetricModule.cryptoModule.signatureAlgorithm;
65327
65328 return UA_STATUSCODE_GOOD;
65329}
65330
65331#endif
65332
65333/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_aes128sha256rsaoaep.c" ****/
65334
65335/* This Source Code Form is subject to the terms of the Mozilla Public
65336 * License, v. 2.0. If a copy of the MPL was not distributed with this
65337 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
65338 *
65339 * Copyright 2020 (c) Wind River Systems, Inc.
65340 */
65341
65342
65343#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
65344
65345
65346#include <openssl/hmac.h>
65347#include <openssl/sha.h>
65348#include <openssl/rsa.h>
65349#include <openssl/x509.h>
65350#include <openssl/rand.h>
65351#include <openssl/rsa.h>
65352
65353#define UA_SHA256_LENGTH 32 /* 256 bit */
65354#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN 42
65355#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH 32
65356#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH 16
65357#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE 16
65358#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE 16
65359#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH 256
65360#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH 512
65361
65362typedef struct {
65363 EVP_PKEY *localPrivateKey;
65364 UA_ByteString localCertThumbprint;
65365 const UA_Logger *logger;
65366} Policy_Context_Aes128Sha256RsaOaep;
65367
65368typedef struct {
65369 UA_ByteString localSymSigningKey;
65370 UA_ByteString localSymEncryptingKey;
65371 UA_ByteString localSymIv;
65372 UA_ByteString remoteSymSigningKey;
65373 UA_ByteString remoteSymEncryptingKey;
65374 UA_ByteString remoteSymIv;
65375
65376 Policy_Context_Aes128Sha256RsaOaep *policyContext;
65377 UA_ByteString remoteCertificate;
65378 X509 *remoteCertificateX509; /* X509 */
65379} Channel_Context_Aes128Sha256RsaOaep;
65380
65381/* create the policy context */
65382
65383static UA_StatusCode
65384UA_Policy_Aes128Sha256RsaOaep_New_Context(UA_SecurityPolicy *securityPolicy,
65385 const UA_ByteString localPrivateKey,
65386 const UA_Logger *logger) {
65387 Policy_Context_Aes128Sha256RsaOaep *context =
65388 (Policy_Context_Aes128Sha256RsaOaep *)UA_malloc(
65389 size: sizeof(Policy_Context_Aes128Sha256RsaOaep));
65390 if(context == NULL) {
65391 return UA_STATUSCODE_BADOUTOFMEMORY;
65392 }
65393
65394 context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey);
65395 if (!context->localPrivateKey) {
65396 UA_free(ptr: context);
65397 return UA_STATUSCODE_BADINVALIDARGUMENT;
65398 }
65399
65400 UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint(
65401 certficate: &securityPolicy->localCertificate, pThumbprint: &context->localCertThumbprint, true);
65402 if(retval != UA_STATUSCODE_GOOD) {
65403 EVP_PKEY_free(pkey: context->localPrivateKey);
65404 UA_free(ptr: context);
65405 return retval;
65406 }
65407
65408 context->logger = logger;
65409 securityPolicy->policyContext = context;
65410
65411 return UA_STATUSCODE_GOOD;
65412}
65413
65414/* clear the policy context */
65415
65416static void
65417UA_Policy_Aes128Sha256RsaOaep_Clear_Context(UA_SecurityPolicy *policy) {
65418 if(policy == NULL)
65419 return;
65420
65421 UA_ByteString_clear(p: &policy->localCertificate);
65422
65423 /* delete all allocated members in the context */
65424
65425 Policy_Context_Aes128Sha256RsaOaep *pc =
65426 (Policy_Context_Aes128Sha256RsaOaep *)policy->policyContext;
65427 if (pc == NULL) {
65428 return;
65429 }
65430
65431 EVP_PKEY_free(pkey: pc->localPrivateKey);
65432 UA_ByteString_clear(p: &pc->localCertThumbprint);
65433 UA_free(ptr: pc);
65434
65435 return;
65436}
65437
65438/* create the channel context */
65439
65440static UA_StatusCode
65441UA_ChannelModule_Aes128Sha256RsaOaep_New_Context(const UA_SecurityPolicy *securityPolicy,
65442 const UA_ByteString *remoteCertificate,
65443 void **channelContext) {
65444 if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL) {
65445 return UA_STATUSCODE_BADINTERNALERROR;
65446 }
65447 Channel_Context_Aes128Sha256RsaOaep *context =
65448 (Channel_Context_Aes128Sha256RsaOaep *)UA_malloc(
65449 size: sizeof(Channel_Context_Aes128Sha256RsaOaep));
65450 if(context == NULL) {
65451 return UA_STATUSCODE_BADOUTOFMEMORY;
65452 }
65453
65454 UA_ByteString_init(p: &context->localSymSigningKey);
65455 UA_ByteString_init(p: &context->localSymEncryptingKey);
65456 UA_ByteString_init(p: &context->localSymIv);
65457 UA_ByteString_init(p: &context->remoteSymSigningKey);
65458 UA_ByteString_init(p: &context->remoteSymEncryptingKey);
65459 UA_ByteString_init(p: &context->remoteSymIv);
65460
65461 UA_StatusCode retval =
65462 UA_copyCertificate(dst: &context->remoteCertificate, src: remoteCertificate);
65463 if(retval != UA_STATUSCODE_GOOD) {
65464 UA_free(ptr: context);
65465 return retval;
65466 }
65467
65468 /* decode to X509 */
65469 context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate);
65470 if (context->remoteCertificateX509 == NULL) {
65471 UA_ByteString_clear (p: &context->remoteCertificate);
65472 UA_free (ptr: context);
65473 return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
65474 }
65475
65476 context->policyContext =
65477 (Policy_Context_Aes128Sha256RsaOaep *)(securityPolicy->policyContext);
65478
65479 *channelContext = context;
65480
65481 UA_LOG_INFO(
65482 logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65483 msg: "The Aes128Sha256RsaOaep security policy channel with openssl is created.");
65484
65485 return UA_STATUSCODE_GOOD;
65486}
65487
65488/* delete the channel context */
65489
65490static void
65491UA_ChannelModule_Aes128Sha256RsaOaep_Delete_Context(void *channelContext) {
65492 if(channelContext != NULL) {
65493 Channel_Context_Aes128Sha256RsaOaep *cc =
65494 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65495 X509_free(a: cc->remoteCertificateX509);
65496 UA_ByteString_clear(p: &cc->remoteCertificate);
65497 UA_ByteString_clear(p: &cc->localSymSigningKey);
65498 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
65499 UA_ByteString_clear(p: &cc->localSymIv);
65500 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
65501 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
65502 UA_ByteString_clear(p: &cc->remoteSymIv);
65503
65504 UA_LOG_INFO(
65505 logger: cc->policyContext->logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65506 msg: "The Aes128Sha256RsaOaep security policy channel with openssl is deleted.");
65507 UA_free(ptr: cc);
65508 }
65509}
65510
65511/* Verifies the signature of the message using the provided keys in the context.
65512 * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256
65513 */
65514
65515static UA_StatusCode
65516UA_AsySig_Aes128Sha256RsaOaep_Verify(void *channelContext, const UA_ByteString *message,
65517 const UA_ByteString *signature) {
65518 if(message == NULL || signature == NULL || channelContext == NULL) {
65519 return UA_STATUSCODE_BADINTERNALERROR;
65520 }
65521
65522 Channel_Context_Aes128Sha256RsaOaep *cc =
65523 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65524 UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(
65525 msg: message, publicKeyX509: cc->remoteCertificateX509, signature);
65526
65527 return retval;
65528}
65529
65530/* Compares the supplied certificate with the certificate
65531 * in the endpoint context
65532 */
65533
65534static UA_StatusCode
65535UA_compareCertificateThumbprint_Aes128Sha256RsaOaep(const UA_SecurityPolicy *securityPolicy,
65536 const UA_ByteString *certificateThumbprint) {
65537 if(securityPolicy == NULL || certificateThumbprint == NULL) {
65538 return UA_STATUSCODE_BADINVALIDARGUMENT;
65539 }
65540 Policy_Context_Aes128Sha256RsaOaep *pc =
65541 (Policy_Context_Aes128Sha256RsaOaep *)securityPolicy->policyContext;
65542 if(!UA_ByteString_equal(string1: certificateThumbprint, string2: &pc->localCertThumbprint))
65543 return UA_STATUSCODE_BADCERTIFICATEINVALID;
65544 return UA_STATUSCODE_GOOD;
65545}
65546
65547/* Generates a thumbprint for the specified certificate */
65548
65549static UA_StatusCode
65550UA_makeCertificateThumbprint_Aes128Sha256RsaOaep(const UA_SecurityPolicy *securityPolicy,
65551 const UA_ByteString *certificate,
65552 UA_ByteString *thumbprint) {
65553 return UA_Openssl_X509_GetCertificateThumbprint(certficate: certificate, pThumbprint: thumbprint, false);
65554}
65555
65556static UA_StatusCode
65557UA_Asym_Aes128Sha256RsaOaep_Decrypt(void *channelContext, UA_ByteString *data) {
65558 if(channelContext == NULL || data == NULL)
65559 return UA_STATUSCODE_BADINVALIDARGUMENT;
65560
65561 Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65562 UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt(data, privateKey: cc->policyContext->localPrivateKey);
65563 return ret;
65564}
65565
65566static size_t
65567UA_Asym_Aes128Sha256RsaOaep_getRemoteSignatureSize(const void *channelContext) {
65568 if(channelContext == NULL)
65569 return UA_STATUSCODE_BADINTERNALERROR;
65570
65571 const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65572 UA_Int32 keyLen = 0;
65573 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65574 return (size_t)keyLen;
65575}
65576
65577static size_t
65578UA_AsySig_Aes128Sha256RsaOaep_getLocalSignatureSize(const void *channelContext) {
65579 if(channelContext == NULL)
65580 return UA_STATUSCODE_BADINTERNALERROR;
65581
65582 const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65583 Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
65584 UA_Int32 keyLen = 0;
65585 UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen);
65586 return (size_t)keyLen;
65587}
65588
65589static size_t
65590UA_AsymEn_Aes128Sha256RsaOaep_getRemotePlainTextBlockSize(const void *channelContext) {
65591 if(channelContext == NULL)
65592 return UA_STATUSCODE_BADINTERNALERROR;
65593
65594 const Channel_Context_Aes128Sha256RsaOaep *cc =
65595 (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65596 UA_Int32 keyLen = 0;
65597 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65598 return (size_t)keyLen - UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
65599}
65600
65601static size_t
65602UA_AsymEn_Aes128Sha256RsaOaep_getRemoteBlockSize(const void *channelContext) {
65603 if(channelContext == NULL)
65604 return UA_STATUSCODE_BADINTERNALERROR;
65605
65606 const Channel_Context_Aes128Sha256RsaOaep *cc =
65607 (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65608 UA_Int32 keyLen = 0;
65609 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65610 return (size_t)keyLen;
65611}
65612
65613static size_t
65614UA_AsymEn_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
65615 if(channelContext == NULL)
65616 return UA_STATUSCODE_BADINTERNALERROR;
65617
65618 const Channel_Context_Aes128Sha256RsaOaep *cc =
65619 (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65620 UA_Int32 keyLen = 0;
65621 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65622 return (size_t)keyLen * 8;
65623}
65624
65625static UA_StatusCode
65626UA_Sym_Aes128Sha256RsaOaep_generateNonce(void *policyContext,
65627 UA_ByteString *out) {
65628 UA_Int32 rc = RAND_bytes(buf: out->data, num: (int)out->length);
65629 if(rc != 1) {
65630 return UA_STATUSCODE_BADUNEXPECTEDERROR;
65631 }
65632 return UA_STATUSCODE_GOOD;
65633}
65634
65635static size_t
65636UA_SymEn_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
65637 /* 32 bytes 256 bits */
65638 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH;
65639}
65640
65641static size_t
65642UA_SymSig_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
65643 /* 32 bytes 256 bits */
65644 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
65645}
65646
65647static UA_StatusCode
65648UA_Sym_Aes128Sha256RsaOaep_generateKey(void *policyContext,
65649 const UA_ByteString *secret,
65650 const UA_ByteString *seed, UA_ByteString *out) {
65651 return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out);
65652}
65653
65654static UA_StatusCode
65655UA_ChannelModule_Aes128Sha256RsaOaep_setLocalSymSigningKey(void *channelContext,
65656 const UA_ByteString *key) {
65657 if(key == NULL || channelContext == NULL)
65658 return UA_STATUSCODE_BADINTERNALERROR;
65659 Channel_Context_Aes128Sha256RsaOaep *cc =
65660 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65661 UA_ByteString_clear(p: &cc->localSymSigningKey);
65662 return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey);
65663}
65664
65665static UA_StatusCode
65666UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymEncryptingKey(void *channelContext,
65667 const UA_ByteString *key) {
65668 if(key == NULL || channelContext == NULL)
65669 return UA_STATUSCODE_BADINTERNALERROR;
65670 Channel_Context_Aes128Sha256RsaOaep *cc =
65671 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65672 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
65673 return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey);
65674}
65675
65676static UA_StatusCode
65677UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymIv(void *channelContext,
65678 const UA_ByteString *iv) {
65679 if(iv == NULL || channelContext == NULL)
65680 return UA_STATUSCODE_BADINTERNALERROR;
65681 Channel_Context_Aes128Sha256RsaOaep *cc =
65682 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65683 UA_ByteString_clear(p: &cc->localSymIv);
65684 return UA_ByteString_copy(src: iv, dst: &cc->localSymIv);
65685}
65686
65687static size_t
65688UA_SymEn_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
65689 /* 32 bytes 256 bits */
65690 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH;
65691}
65692
65693static size_t
65694UA_SymEn_Aes128Sha256RsaOaep_getBlockSize(const void *channelContext) {
65695 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
65696}
65697
65698static size_t
65699UA_SymSig_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
65700 /* 32 bytes 256 bits */
65701 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
65702}
65703
65704static UA_StatusCode
65705UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymSigningKey(void *channelContext,
65706 const UA_ByteString *key) {
65707 if(key == NULL || channelContext == NULL)
65708 return UA_STATUSCODE_BADINTERNALERROR;
65709 Channel_Context_Aes128Sha256RsaOaep *cc =
65710 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65711 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
65712 return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey);
65713}
65714
65715static UA_StatusCode
65716UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymEncryptingKey(void *channelContext,
65717 const UA_ByteString *key) {
65718 if(key == NULL || channelContext == NULL)
65719 return UA_STATUSCODE_BADINTERNALERROR;
65720 Channel_Context_Aes128Sha256RsaOaep *cc =
65721 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65722 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
65723 return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey);
65724}
65725
65726static UA_StatusCode
65727UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymIv(void *channelContext,
65728 const UA_ByteString *key) {
65729 if(key == NULL || channelContext == NULL)
65730 return UA_STATUSCODE_BADINTERNALERROR;
65731 Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65732 UA_ByteString_clear(p: &cc->remoteSymIv);
65733 return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv);
65734}
65735
65736static UA_StatusCode
65737UA_AsySig_Aes128Sha256RsaOaep_sign(void *channelContext, const UA_ByteString *message,
65738 UA_ByteString *signature) {
65739 if(channelContext == NULL || message == NULL ||
65740 signature == NULL)
65741 return UA_STATUSCODE_BADINTERNALERROR;
65742 Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65743 Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
65744 return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, privateKey: pc->localPrivateKey, outSignature: signature);
65745}
65746
65747static UA_StatusCode
65748UA_AsymEn_Aes128Sha256RsaOaep_encrypt(void *channelContext, UA_ByteString *data) {
65749 if(channelContext == NULL || data == NULL)
65750 return UA_STATUSCODE_BADINTERNALERROR;
65751 Channel_Context_Aes128Sha256RsaOaep *cc =
65752 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65753 return UA_Openssl_RSA_OAEP_Encrypt(
65754 data, UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN,
65755 publicX509: cc->remoteCertificateX509);
65756}
65757
65758static size_t
65759UA_SymSig_Aes128Sha256RsaOaep_getRemoteSignatureSize(const void *channelContext) {
65760 return UA_SHA256_LENGTH;
65761}
65762
65763static UA_StatusCode
65764UA_SymSig_Aes128Sha256RsaOaep_verify(void *channelContext, const UA_ByteString *message,
65765 const UA_ByteString *signature) {
65766 if(channelContext == NULL || message == NULL ||
65767 signature == NULL)
65768 return UA_STATUSCODE_BADINTERNALERROR;
65769
65770 Channel_Context_Aes128Sha256RsaOaep *cc =
65771 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65772 return UA_OpenSSL_HMAC_SHA256_Verify(message, key: &cc->remoteSymSigningKey, signature);
65773}
65774
65775static UA_StatusCode
65776UA_SymSig_Aes128Sha256RsaOaep_sign(void *channelContext, const UA_ByteString *message,
65777 UA_ByteString *signature) {
65778 if(channelContext == NULL || message == NULL ||
65779 signature == NULL)
65780 return UA_STATUSCODE_BADINTERNALERROR;
65781
65782 Channel_Context_Aes128Sha256RsaOaep *cc =
65783 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65784 return UA_OpenSSL_HMAC_SHA256_Sign(message, key: &cc->localSymSigningKey, signature);
65785}
65786
65787static size_t
65788UA_SymSig_Aes128Sha256RsaOaep_getLocalSignatureSize(const void *channelContext) {
65789 return UA_SHA256_LENGTH;
65790}
65791
65792static UA_StatusCode
65793UA_SymEn_Aes128Sha256RsaOaep_decrypt(void *channelContext, UA_ByteString *data) {
65794 if(channelContext == NULL || data == NULL)
65795 return UA_STATUSCODE_BADINTERNALERROR;
65796 Channel_Context_Aes128Sha256RsaOaep *cc =
65797 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65798 return UA_OpenSSL_AES_128_CBC_Decrypt(iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey,
65799 data);
65800}
65801
65802static UA_StatusCode
65803UA_SymEn_Aes128Sha256RsaOaep_encrypt(void *channelContext, UA_ByteString *data) {
65804 if(channelContext == NULL || data == NULL)
65805 return UA_STATUSCODE_BADINTERNALERROR;
65806
65807 Channel_Context_Aes128Sha256RsaOaep *cc =
65808 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65809 return UA_OpenSSL_AES_128_CBC_Encrypt(iv: &cc->localSymIv, key: &cc->localSymEncryptingKey,
65810 data);
65811}
65812
65813static UA_StatusCode
65814UA_ChannelM_Aes128Sha256RsaOaep_compareCertificate(const void *channelContext,
65815 const UA_ByteString *certificate) {
65816 if(channelContext == NULL || certificate == NULL)
65817 return UA_STATUSCODE_BADINTERNALERROR;
65818
65819 const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65820 return UA_OpenSSL_X509_compare(cert: certificate, bcert: cc->remoteCertificateX509);
65821}
65822
65823static size_t
65824UA_AsymEn_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
65825 if(channelContext == NULL)
65826 return UA_STATUSCODE_BADINTERNALERROR;
65827
65828 const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65829 Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
65830 UA_Int32 keyLen = 0;
65831 UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen);
65832 return (size_t)keyLen * 8;
65833}
65834
65835/* the main entry of Aes128Sha256RsaOaep */
65836
65837UA_StatusCode
65838UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy,
65839 const UA_ByteString localCertificate,
65840 const UA_ByteString localPrivateKey,
65841 const UA_Logger *logger) {
65842
65843 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
65844 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
65845 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
65846 UA_StatusCode retval;
65847
65848 UA_LOG_INFO(logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65849 msg: "The Aes128Sha256RsaOaep security policy with openssl is added.");
65850
65851 UA_Openssl_Init();
65852 memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy));
65853 policy->logger = logger;
65854 policy->policyUri =
65855 UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep\0");
65856
65857 /* set ChannelModule context */
65858
65859 channelModule->newContext = UA_ChannelModule_Aes128Sha256RsaOaep_New_Context;
65860 channelModule->deleteContext = UA_ChannelModule_Aes128Sha256RsaOaep_Delete_Context;
65861 channelModule->setLocalSymSigningKey =
65862 UA_ChannelModule_Aes128Sha256RsaOaep_setLocalSymSigningKey;
65863 channelModule->setLocalSymEncryptingKey =
65864 UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymEncryptingKey;
65865 channelModule->setLocalSymIv = UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymIv;
65866 channelModule->setRemoteSymSigningKey =
65867 UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymSigningKey;
65868 channelModule->setRemoteSymEncryptingKey =
65869 UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymEncryptingKey;
65870 channelModule->setRemoteSymIv = UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymIv;
65871 channelModule->compareCertificate =
65872 UA_ChannelM_Aes128Sha256RsaOaep_compareCertificate;
65873
65874 /* Copy the certificate and add a NULL to the end */
65875
65876 retval = UA_copyCertificate(dst: &policy->localCertificate, src: &localCertificate);
65877 if(retval != UA_STATUSCODE_GOOD)
65878 return retval;
65879
65880 /* AsymmetricModule - signature algorithm */
65881
65882 UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm =
65883 &asymmetricModule->cryptoModule.signatureAlgorithm;
65884 asySigAlgorithm->uri =
65885 UA_STRING(chars: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
65886 asySigAlgorithm->verify = UA_AsySig_Aes128Sha256RsaOaep_Verify;
65887 asySigAlgorithm->getRemoteSignatureSize =
65888 UA_Asym_Aes128Sha256RsaOaep_getRemoteSignatureSize;
65889 asySigAlgorithm->getLocalSignatureSize =
65890 UA_AsySig_Aes128Sha256RsaOaep_getLocalSignatureSize;
65891 asySigAlgorithm->sign = UA_AsySig_Aes128Sha256RsaOaep_sign;
65892 asySigAlgorithm->getLocalKeyLength = NULL;
65893 asySigAlgorithm->getRemoteKeyLength = NULL;
65894
65895 /* AsymmetricModule encryption algorithm */
65896
65897 UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg =
65898 &asymmetricModule->cryptoModule.encryptionAlgorithm;
65899 asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
65900 asymEncryAlg->decrypt = UA_Asym_Aes128Sha256RsaOaep_Decrypt;
65901 asymEncryAlg->getRemotePlainTextBlockSize =
65902 UA_AsymEn_Aes128Sha256RsaOaep_getRemotePlainTextBlockSize;
65903 asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Aes128Sha256RsaOaep_getRemoteBlockSize;
65904 asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Aes128Sha256RsaOaep_getRemoteKeyLength;
65905 asymEncryAlg->encrypt = UA_AsymEn_Aes128Sha256RsaOaep_encrypt;
65906 asymEncryAlg->getLocalKeyLength = UA_AsymEn_Aes128Sha256RsaOaep_getLocalKeyLength;
65907
65908 /* asymmetricModule */
65909
65910 asymmetricModule->compareCertificateThumbprint =
65911 UA_compareCertificateThumbprint_Aes128Sha256RsaOaep;
65912 asymmetricModule->makeCertificateThumbprint =
65913 UA_makeCertificateThumbprint_Aes128Sha256RsaOaep;
65914
65915 /* SymmetricModule */
65916
65917 symmetricModule->secureChannelNonceLength = 32;
65918 symmetricModule->generateNonce = UA_Sym_Aes128Sha256RsaOaep_generateNonce;
65919 symmetricModule->generateKey = UA_Sym_Aes128Sha256RsaOaep_generateKey;
65920
65921 /* Symmetric encryption Algorithm */
65922
65923 UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm =
65924 &symmetricModule->cryptoModule.encryptionAlgorithm;
65925 symEncryptionAlgorithm->uri =
65926 UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes128-cbc\0");
65927 symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Aes128Sha256RsaOaep_getLocalKeyLength;
65928 symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Aes128Sha256RsaOaep_getRemoteKeyLength;
65929 symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Aes128Sha256RsaOaep_getBlockSize;
65930 symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Aes128Sha256RsaOaep_getBlockSize;
65931 symEncryptionAlgorithm->decrypt = UA_SymEn_Aes128Sha256RsaOaep_decrypt;
65932 symEncryptionAlgorithm->encrypt = UA_SymEn_Aes128Sha256RsaOaep_encrypt;
65933
65934 /* Symmetric signature Algorithm */
65935
65936 UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm =
65937 &symmetricModule->cryptoModule.signatureAlgorithm;
65938 symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0");
65939 symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Aes128Sha256RsaOaep_getLocalKeyLength;
65940 symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Aes128Sha256RsaOaep_getRemoteKeyLength;
65941 symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Aes128Sha256RsaOaep_getRemoteSignatureSize;
65942 symSignatureAlgorithm->verify = UA_SymSig_Aes128Sha256RsaOaep_verify;
65943 symSignatureAlgorithm->sign = UA_SymSig_Aes128Sha256RsaOaep_sign;
65944 symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Aes128Sha256RsaOaep_getLocalSignatureSize;
65945
65946 retval = UA_Policy_Aes128Sha256RsaOaep_New_Context(securityPolicy: policy, localPrivateKey, logger);
65947 if(retval != UA_STATUSCODE_GOOD) {
65948 UA_ByteString_clear(p: &policy->localCertificate);
65949 return retval;
65950 }
65951 policy->clear = UA_Policy_Aes128Sha256RsaOaep_Clear_Context;
65952
65953 /* Use the same signature algorithm as the asymmetric component for
65954 certificate signing (see standard) */
65955
65956 policy->certificateSigningAlgorithm =
65957 policy->asymmetricModule.cryptoModule.signatureAlgorithm;
65958
65959 return UA_STATUSCODE_GOOD;
65960}
65961
65962#endif
65963
65964/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_create_certificate.c" ****/
65965
65966/* This Source Code Form is subject to the terms of the Mozilla Public
65967 * License, v. 2.0. If a copy of the MPL was not distributed with this
65968 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
65969 *
65970 * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
65971 * Copyright 2022 (c) Wind River Systems, Inc.
65972 *
65973 */
65974
65975
65976
65977#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
65978
65979
65980#include <openssl/pem.h>
65981#include <openssl/x509v3.h>
65982
65983/**
65984 * Join an array of UA_String to a single NULL-Terminated UA_String
65985 * separated by character sep
65986 */
65987static UA_StatusCode
65988join_string_with_sep(const UA_String *strings, size_t stringsSize,
65989 char sep, UA_String *out) {
65990 if(!out)
65991 return UA_STATUSCODE_BADINVALIDARGUMENT;
65992
65993 UA_String_clear(p: out);
65994 size_t totalSize = stringsSize;
65995 for(size_t iStr = 0; iStr < stringsSize; ++iStr) {
65996 totalSize += strings[iStr].length;
65997 }
65998
65999 UA_ByteString_allocBuffer(bs: out, length: totalSize);
66000 if(!out->data) {
66001 return UA_STATUSCODE_BADOUTOFMEMORY;
66002 }
66003
66004 size_t pos = 0;
66005 for(size_t iStr = 0; iStr < stringsSize; ++iStr) {
66006 memcpy(dest: &out->data[pos], src: strings[iStr].data, n: strings[iStr].length);
66007 pos += strings[iStr].length;
66008 out->data[pos] = (UA_Byte) sep;
66009 ++pos;
66010 }
66011 out->data[out->length-1] = 0;
66012
66013 return UA_STATUSCODE_GOOD;
66014}
66015
66016/**
66017 * Search for a character in a string (like strchr).
66018 * \todo Handle UTF-8
66019 *
66020 * \return index of the character or -1 on case of an error.
66021 */
66022
66023static UA_Int32
66024UA_String_chr(const UA_String *pUaStr, char needl) {
66025 UA_Byte byteNeedl = (UA_Byte)needl;
66026 for(size_t i = 0; (size_t)i < pUaStr->length; ++i) {
66027 if(pUaStr->data[i] == byteNeedl) {
66028 return (UA_Int32) i;
66029 }
66030 }
66031 return -1;
66032}
66033
66034static UA_StatusCode
66035add_x509V3ext(X509 *x509, int nid, const char *value) {
66036 X509_EXTENSION *ex;
66037 X509V3_CTX ctx;
66038 X509V3_set_ctx_nodb(&ctx);
66039 X509V3_set_ctx(ctx: &ctx, issuer: x509, subject: x509, NULL, NULL, flags: 0);
66040 ex = X509V3_EXT_conf_nid(NULL, ctx: &ctx, ext_nid: nid, value);
66041 if(!ex)
66042 return UA_STATUSCODE_BADINTERNALERROR;
66043 X509_add_ext(x: x509, ex, loc: -1);
66044 X509_EXTENSION_free(a: ex);
66045 return UA_STATUSCODE_GOOD;
66046}
66047
66048#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
66049
66050/* generate the RSA key */
66051
66052static EVP_PKEY * UA_RSA_Generate_Key (size_t keySizeBits){
66053 return EVP_RSA_gen(keySizeBits);
66054}
66055
66056#endif
66057
66058UA_StatusCode
66059UA_CreateCertificate(const UA_Logger *logger,
66060 const UA_String *subject, size_t subjectSize,
66061 const UA_String *subjectAltName, size_t subjectAltNameSize,
66062 size_t keySizeBits, UA_CertificateFormat certFormat,
66063 UA_ByteString *outPrivateKey, UA_ByteString *outCertificate) {
66064 if(!outPrivateKey || !outCertificate || !logger || !subjectAltName ||
66065 !subject || subjectAltNameSize == 0 || subjectSize == 0 ||
66066 (certFormat != UA_CERTIFICATEFORMAT_DER && certFormat != UA_CERTIFICATEFORMAT_PEM ))
66067 return UA_STATUSCODE_BADINVALIDARGUMENT;
66068
66069 /* Use the maximum size */
66070 if(keySizeBits == 0)
66071 keySizeBits = 4096;
66072
66073 UA_ByteString_init(p: outPrivateKey);
66074 UA_ByteString_init(p: outCertificate);
66075
66076 UA_String fullAltSubj = UA_STRING_NULL;
66077 UA_Int32 serial = 1;
66078
66079 /** \TODO: Seed Random generator
66080 * See: (https://www.openssl.org/docs/man1.1.0/man3/RAND_add.html) */
66081 BIO *memCert = NULL;
66082 BIO *memPKey = NULL;
66083
66084 UA_StatusCode errRet = UA_STATUSCODE_GOOD;
66085
66086 X509 *x509 = X509_new();
66087
66088#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
66089 EVP_PKEY *pkey = UA_RSA_Generate_Key(keySizeBits);
66090 if((pkey == NULL) || (x509 == NULL)) {
66091 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66092 goto cleanup;
66093 }
66094#else
66095 BIGNUM *exponent = BN_new();
66096 EVP_PKEY *pkey = EVP_PKEY_new();
66097 RSA *rsa = RSA_new();
66098 if(!pkey || !x509 || !exponent || !rsa) {
66099 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66100 goto cleanup;
66101 }
66102
66103 UA_LOG_INFO(logger, UA_LOGCATEGORY_SECURECHANNEL,
66104 "Create Certificate: Generating RSA key. This may take a while.");
66105
66106 if(BN_set_word(exponent, RSA_F4) != 1) {
66107 UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
66108 "Create Certificate: Setting RSA exponent failed.");
66109 errRet = UA_STATUSCODE_BADINTERNALERROR;
66110 goto cleanup;
66111 }
66112
66113 if(RSA_generate_key_ex(rsa, (int) keySizeBits, exponent, NULL) != 1) {
66114 UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
66115 "Create Certificate: Generating RSA key failed.");
66116 errRet = UA_STATUSCODE_BADINTERNALERROR;
66117 goto cleanup;
66118 }
66119
66120 if(EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
66121 UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
66122 "Create Certificate: Assign RSA key failed.");
66123 errRet = UA_STATUSCODE_BADINTERNALERROR;
66124 goto cleanup;
66125 }
66126 /* rsa will be freed by pkey */
66127 rsa = NULL;
66128
66129#endif /* end of OPENSSL_VERSION_NUMBER >= 0x30000000L */
66130
66131 /* x509v3 has version 2
66132 * (https://www.openssl.org/docs/man1.1.0/man3/X509_set_version.html) */
66133 if(X509_set_version(x: x509, version: 2) != 1) {
66134 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66135 msg: "Create Certificate: Setting version failed.");
66136 errRet = UA_STATUSCODE_BADINTERNALERROR;
66137 goto cleanup;
66138 }
66139
66140 if(ASN1_INTEGER_set(a: X509_get_serialNumber(x: x509), v: serial) != 1) {
66141 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66142 msg: "Create Certificate: Setting serial number failed.");
66143 /* Only memory errors are possible */
66144 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66145 goto cleanup;
66146 }
66147
66148 if(X509_gmtime_adj(X509_get_notBefore(x: x509), adj: 0) == NULL) {
66149 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66150 msg: "Create Certificate: Setting 'not before' failed.");
66151 errRet = UA_STATUSCODE_BADINTERNALERROR;
66152 goto cleanup;
66153 }
66154
66155 if(X509_gmtime_adj(X509_get_notAfter(x: x509), adj: (UA_Int64) 60 * 60 * 24 * 365) == NULL) {
66156 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66157 msg: "Create Certificate: Setting 'not before' failed.");
66158 errRet = UA_STATUSCODE_BADINTERNALERROR;
66159 goto cleanup;
66160 }
66161
66162 if(X509_set_pubkey(x: x509, pkey) != 1) {
66163 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66164 msg: "Create Certificate: Setting publik key failed.");
66165 errRet = UA_STATUSCODE_BADINTERNALERROR;
66166 goto cleanup;
66167 }
66168
66169 X509_NAME *name = X509_get_subject_name(a: x509);
66170 if(name == NULL) {
66171 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66172 msg: "Create Certificate: Getting name failed.");
66173 errRet = UA_STATUSCODE_BADINTERNALERROR;
66174 goto cleanup;
66175 }
66176
66177 for(UA_UInt32 iSubject = 0; iSubject < subjectSize; ++iSubject) {
66178 UA_Int32 sep = UA_String_chr(pUaStr: &subject[iSubject], needl: '=');
66179 char field[16];
66180 if(sep == -1 || sep == 0 ||
66181 ((size_t) sep == (subject[iSubject].length - 1)) || sep >= 15) {
66182 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66183 msg: "Create Certificate: Subject must contain one '=' with "
66184 "content before and after.");
66185 errRet = UA_STATUSCODE_BADINTERNALERROR;
66186 goto cleanup;
66187 }
66188 memcpy(dest: field, src: subject[iSubject].data, n: (size_t) sep);
66189 field[sep] = 0;
66190 UA_Byte* pData = &subject[iSubject].data[sep + 1];
66191 if(X509_NAME_add_entry_by_txt(
66192 name, field, MBSTRING_ASC,
66193 bytes: (const unsigned char *)pData,
66194 len: (int) subject[iSubject].length - (int) sep - 1, loc: -1, set: 0) != 1) {
66195 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66196 msg: "Create Certificate: Setting subject failed.");
66197 errRet = UA_STATUSCODE_BADINTERNALERROR;
66198 goto cleanup;
66199 }
66200 }
66201 /* Self signed, so issuer == subject */
66202 if(X509_set_issuer_name(x: x509, name) != 1) {
66203 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66204 msg: "Create Certificate: Setting name failed.");
66205 errRet = UA_STATUSCODE_BADINTERNALERROR;
66206 goto cleanup;
66207 }
66208
66209 errRet = add_x509V3ext(x509, NID_basic_constraints, value: "CA:FALSE");
66210 if(errRet != UA_STATUSCODE_GOOD) {
66211 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66212 msg: "Create Certificate: Setting 'Basic Constraints' failed.");
66213 goto cleanup;
66214 }
66215
66216 /* See https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3 for
66217 * possible values */
66218 errRet = add_x509V3ext(x509, NID_key_usage,
66219 value: "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyCertSign");
66220 if(errRet != UA_STATUSCODE_GOOD) {
66221 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66222 msg: "Create Certificate: Setting 'Key Usage' failed.");
66223 goto cleanup;
66224 }
66225
66226 errRet = add_x509V3ext(x509, NID_ext_key_usage, value: "serverAuth,clientAuth");
66227 if(errRet != UA_STATUSCODE_GOOD) {
66228 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66229 msg: "Create Certificate: Setting 'Extended Key Usage' failed.");
66230 goto cleanup;
66231 }
66232
66233 errRet = add_x509V3ext(x509, NID_subject_key_identifier, value: "hash");
66234 if(errRet != UA_STATUSCODE_GOOD) {
66235 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66236 msg: "Create Certificate: Setting 'Subject Key Identifier' failed.");
66237 goto cleanup;
66238 }
66239
66240 errRet = join_string_with_sep(strings: subjectAltName, stringsSize: subjectAltNameSize, sep: ',', out: &fullAltSubj);
66241 if(errRet != UA_STATUSCODE_GOOD) {
66242 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66243 msg: "Create Certificate: Joining altSubject failed.");
66244 goto cleanup;
66245 }
66246
66247 errRet = add_x509V3ext(x509, NID_subject_alt_name, value: (const char*) fullAltSubj.data);
66248 if(errRet != UA_STATUSCODE_GOOD) {
66249 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66250 msg: "Create Certificate: Setting 'Subject Alternative Name:' failed.");
66251 goto cleanup;
66252 }
66253
66254 if(X509_sign(x: x509, pkey, md: EVP_sha256()) == 0) {
66255 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66256 msg: "Create Certificate: Signing failed.");
66257 errRet = UA_STATUSCODE_BADINTERNALERROR;
66258 goto cleanup;
66259 }
66260
66261 switch(certFormat) {
66262 case UA_CERTIFICATEFORMAT_DER: {
66263 int tmpLen = i2d_PrivateKey(a: pkey, pp: &outPrivateKey->data);
66264 if(tmpLen <= 0) {
66265 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66266 msg: "Create Certificate: Create private DER key failed.");
66267 errRet = UA_STATUSCODE_BADINTERNALERROR;
66268 goto cleanup;
66269 }
66270 outPrivateKey->length = (size_t) tmpLen;
66271
66272 tmpLen = i2d_X509(a: x509, out: &outCertificate->data);
66273 if(tmpLen <= 0) {
66274 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66275 msg: "Create Certificate: Create DER-certificate failed.");
66276 errRet = UA_STATUSCODE_BADINTERNALERROR;
66277 goto cleanup;
66278 }
66279 outCertificate->length = (size_t) tmpLen;
66280 break;
66281 }
66282 case UA_CERTIFICATEFORMAT_PEM: {
66283 /* Private Key */
66284 memPKey = BIO_new(type: BIO_s_mem());
66285 if(!memPKey) {
66286 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66287 msg: "Create Certificate: Allocate Membuffer for PKey failed.");
66288 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66289 goto cleanup;
66290 }
66291
66292 if(PEM_write_bio_PrivateKey(out: memPKey, x: pkey, NULL, NULL, klen: 0, cb: 0, NULL) != 1) {
66293 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66294 msg: "Create Certificate: Generate PEM-PrivateKey failed.");
66295 errRet = UA_STATUSCODE_BADINTERNALERROR;
66296 goto cleanup;
66297 }
66298
66299 UA_ByteString tmpPem = UA_BYTESTRING_NULL;
66300 tmpPem.length = (size_t) BIO_get_mem_data(memPKey, &tmpPem.data);
66301 errRet = UA_ByteString_copy(src: &tmpPem, dst: outPrivateKey);
66302 if(errRet != UA_STATUSCODE_GOOD) {
66303 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66304 msg: "Create Certificate: Copy PEM PKey failed.");
66305 goto cleanup;
66306 }
66307
66308 /* Certificate */
66309 memCert = BIO_new(type: BIO_s_mem());
66310 if(!memCert) {
66311 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66312 msg: "Create Certificate: Allocate Membuffer for Cert failed.");
66313 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66314 goto cleanup;
66315 }
66316
66317 if(PEM_write_bio_X509(out: memCert, x: x509) != 1) {
66318 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66319 msg: "Create Certificate: Generate PEM-Certifcate failed.");
66320 errRet = UA_STATUSCODE_BADINTERNALERROR;
66321 goto cleanup;
66322 }
66323
66324 tmpPem.length = (size_t) BIO_get_mem_data(memCert, &tmpPem.data);
66325 errRet = UA_ByteString_copy(src: &tmpPem, dst: outCertificate);
66326 if(errRet != UA_STATUSCODE_GOOD) {
66327 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66328 msg: "Create Certificate: Copy PEM Certificate failed.");
66329 goto cleanup;
66330 }
66331 break;
66332 }
66333 }
66334
66335cleanup:
66336 UA_String_clear(p: &fullAltSubj);
66337#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
66338 RSA_free(rsa);
66339 BN_free(exponent);
66340#endif
66341 X509_free(a: x509);
66342 EVP_PKEY_free(pkey);
66343 BIO_free(a: memCert);
66344 BIO_free(a: memPKey);
66345 return errRet;
66346}
66347
66348#endif
66349
66350/**** amalgamated original file "/plugins/crypto/openssl/ua_pki_openssl.c" ****/
66351
66352/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
66353 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
66354 *
66355 * Copyright 2020 (c) Wind River Systems, Inc.
66356 * Copyright 2020 (c) basysKom GmbH
66357
66358 */
66359
66360
66361
66362#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
66363#include <openssl/x509.h>
66364#include <openssl/x509_vfy.h>
66365#include <openssl/x509v3.h>
66366#include <openssl/pem.h>
66367
66368
66369/* Find binary substring. Taken and adjusted from
66370 * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */
66371
66372static const unsigned char *
66373bstrchr(const unsigned char *s, const unsigned char ch, size_t l) {
66374 /* find first occurrence of c in char s[] for length l*/
66375 for(; l > 0; ++s, --l) {
66376 if(*s == ch)
66377 return s;
66378 }
66379 return NULL;
66380}
66381
66382static const unsigned char *
66383UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) {
66384 /* find first occurrence of s2[] in s1[] for length l1*/
66385 const unsigned char *ss1 = s1;
66386 const unsigned char *ss2 = s2;
66387 /* handle special case */
66388 if(l1 == 0)
66389 return (NULL);
66390 if(l2 == 0)
66391 return s1;
66392
66393 /* match prefix */
66394 for (; (s1 = bstrchr(s: s1, ch: *s2, l: (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL &&
66395 (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) {
66396
66397 /* match rest of prefix */
66398 const unsigned char *sc1, *sc2;
66399 for (sc1 = s1, sc2 = s2; ;)
66400 if (++sc2 >= ss2+l2)
66401 return s1;
66402 else if (*++sc1 != *sc2)
66403 break;
66404 }
66405 return NULL;
66406}
66407
66408typedef struct {
66409 /*
66410 * If the folders are defined, we use them to reload the certificates during
66411 * runtime
66412 */
66413
66414 UA_String trustListFolder;
66415 UA_String issuerListFolder;
66416 UA_String revocationListFolder;
66417
66418 STACK_OF(X509) * skIssue;
66419 STACK_OF(X509) * skTrusted;
66420 STACK_OF(X509_CRL) * skCrls; /* Revocation list*/
66421} CertContext;
66422
66423static UA_StatusCode
66424UA_CertContext_sk_Init (CertContext * context) {
66425 context->skTrusted = sk_X509_new_null();
66426 context->skIssue = sk_X509_new_null();
66427 context->skCrls = sk_X509_CRL_new_null();
66428 if (context->skTrusted == NULL || context->skIssue == NULL ||
66429 context->skCrls == NULL) {
66430 return UA_STATUSCODE_BADOUTOFMEMORY;
66431 }
66432 return UA_STATUSCODE_GOOD;
66433}
66434
66435static void
66436UA_CertContext_sk_free (CertContext * context) {
66437 sk_X509_pop_free (context->skTrusted, X509_free);
66438 sk_X509_pop_free (context->skIssue, X509_free);
66439 sk_X509_CRL_pop_free (context->skCrls, X509_CRL_free);
66440}
66441
66442static UA_StatusCode
66443UA_CertContext_Init (CertContext * context) {
66444 (void) memset (s: context, c: 0, n: sizeof (CertContext));
66445 UA_ByteString_init (p: &context->trustListFolder);
66446 UA_ByteString_init (p: &context->issuerListFolder);
66447 UA_ByteString_init (p: &context->revocationListFolder);
66448 return UA_CertContext_sk_Init (context);
66449}
66450
66451static void
66452UA_CertificateVerification_clear (UA_CertificateVerification * cv) {
66453 if (cv == NULL) {
66454 return ;
66455 }
66456 CertContext * context = (CertContext *) cv->context;
66457 if (context == NULL) {
66458 return;
66459 }
66460 UA_ByteString_clear (p: &context->trustListFolder);
66461 UA_ByteString_clear (p: &context->issuerListFolder);
66462 UA_ByteString_clear (p: &context->revocationListFolder);
66463
66464 UA_CertContext_sk_free (context);
66465 UA_free (ptr: context);
66466
66467 cv->context = NULL;
66468
66469 return;
66470}
66471
66472static UA_StatusCode
66473UA_skTrusted_Cert2X509 (const UA_ByteString * certificateTrustList,
66474 size_t certificateTrustListSize,
66475 CertContext * ctx) {
66476 size_t i;
66477
66478 for (i = 0; i < certificateTrustListSize; i++) {
66479 X509 * x509 = UA_OpenSSL_LoadCertificate(certificate: &certificateTrustList[i]);
66480
66481 if (x509 == NULL) {
66482 return UA_STATUSCODE_BADINTERNALERROR;
66483 }
66484 sk_X509_push (ctx->skTrusted, x509);
66485 }
66486
66487 return UA_STATUSCODE_GOOD;
66488}
66489
66490static UA_StatusCode
66491UA_skIssuer_Cert2X509 (const UA_ByteString * certificateIssuerList,
66492 size_t certificateIssuerListSize,
66493 CertContext * ctx) {
66494 size_t i;
66495
66496 for (i = 0; i < certificateIssuerListSize; i++) {
66497 X509 * x509 = UA_OpenSSL_LoadCertificate(certificate: &certificateIssuerList[i]);
66498
66499 if (x509 == NULL) {
66500 return UA_STATUSCODE_BADINTERNALERROR;
66501 }
66502 sk_X509_push (ctx->skIssue, x509);
66503 }
66504
66505 return UA_STATUSCODE_GOOD;
66506}
66507
66508static UA_StatusCode
66509UA_skCrls_Cert2X509 (const UA_ByteString * certificateRevocationList,
66510 size_t certificateRevocationListSize,
66511 CertContext * ctx) {
66512 size_t i;
66513 const unsigned char * pData;
66514
66515 for (i = 0; i < certificateRevocationListSize; i++) {
66516 pData = certificateRevocationList[i].data;
66517 X509_CRL * crl = NULL;
66518
66519 if (certificateRevocationList[i].length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files
66520 crl = d2i_X509_CRL (NULL, in: &pData, len: (long) certificateRevocationList[i].length);
66521 } else {
66522 BIO* bio = NULL;
66523 bio = BIO_new_mem_buf(buf: (void *) certificateRevocationList[i].data,
66524 len: (int) certificateRevocationList[i].length);
66525 crl = PEM_read_bio_X509_CRL(out: bio, NULL, NULL, NULL);
66526 BIO_free(a: bio);
66527 }
66528
66529 if (crl == NULL) {
66530 return UA_STATUSCODE_BADINTERNALERROR;
66531 }
66532 sk_X509_CRL_push (ctx->skCrls, crl);
66533 }
66534
66535 return UA_STATUSCODE_GOOD;
66536}
66537
66538#ifdef __linux__
66539#include <dirent.h>
66540
66541static int UA_Certificate_Filter_der_pem (const struct dirent * entry) {
66542 /* ignore hidden files */
66543 if (entry->d_name[0] == '.') return 0;
66544
66545 /* check file extension */
66546 const char *pszFind = strrchr(s: entry->d_name, c: '.');
66547 if (pszFind == 0)
66548 return 0;
66549 pszFind++;
66550 if (strcmp (s1: pszFind, s2: "der") == 0 || strcmp (s1: pszFind, s2: "pem") == 0)
66551 return 1;
66552
66553 return 0;
66554}
66555
66556static int UA_Certificate_Filter_crl (const struct dirent * entry) {
66557
66558 /* ignore hidden files */
66559 if (entry->d_name[0] == '.') return 0;
66560
66561 /* check file extension */
66562 const char *pszFind = strrchr(s: entry->d_name, c: '.');
66563 if (pszFind == 0)
66564 return 0;
66565 pszFind++;
66566 if (strcmp (s1: pszFind, s2: "crl") == 0)
66567 return 1;
66568
66569 return 0;
66570}
66571
66572static UA_StatusCode
66573UA_BuildFullPath (const char * path,
66574 const char * fileName,
66575 size_t fullPathBufferLength,
66576 char * fullPath) {
66577 size_t pathLen = strlen (s: path);
66578 size_t fileNameLen = strlen (s: fileName);
66579 if ((pathLen + fileNameLen + 2) > fullPathBufferLength) {
66580 return UA_STATUSCODE_BADINVALIDARGUMENT;
66581 }
66582 strcpy (dest: fullPath, src: path);
66583 strcat (dest: fullPath, src: "/");
66584 strcat (dest: fullPath, src: fileName);
66585
66586 return UA_STATUSCODE_GOOD;
66587}
66588
66589static UA_StatusCode
66590UA_loadCertFromFile (const char * fileName,
66591 UA_ByteString * cert) {
66592
66593 FILE * fp = fopen(filename: fileName, modes: "rb");
66594
66595 if (fp == NULL)
66596 return UA_STATUSCODE_BADINTERNALERROR;
66597
66598 fseek(stream: fp, off: 0, SEEK_END);
66599 cert->length = (size_t) ftell(stream: fp);
66600 if (UA_ByteString_allocBuffer (bs: cert, length: cert->length) != UA_STATUSCODE_GOOD) {
66601 fclose (stream: fp);
66602 return UA_STATUSCODE_BADOUTOFMEMORY;
66603 }
66604 fseek(stream: fp, off: 0, SEEK_SET);
66605 size_t readLen = fread (ptr: cert->data, size: 1, n: cert->length, stream: fp);
66606 if (readLen != cert->length) {
66607 UA_ByteString_clear (p: cert);
66608 cert->length = 0;
66609 fclose (stream: fp);
66610 return UA_STATUSCODE_BADINTERNALERROR;
66611 }
66612 fclose (stream: fp);
66613
66614 return UA_STATUSCODE_GOOD;
66615}
66616
66617static UA_StatusCode
66618UA_ReloadCertFromFolder (CertContext * ctx) {
66619 UA_StatusCode ret;
66620 struct dirent ** dirlist = NULL;
66621 int i;
66622 int numCertificates;
66623 char certFile[PATH_MAX];
66624 UA_ByteString strCert;
66625 char folderPath[PATH_MAX];
66626
66627 UA_ByteString_init (p: &strCert);
66628
66629 if (ctx->trustListFolder.length > 0) {
66630 UA_LOG_INFO(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the trust-list");
66631
66632 sk_X509_pop_free (ctx->skTrusted, X509_free);
66633 ctx->skTrusted = sk_X509_new_null();
66634 if (ctx->skTrusted == NULL) {
66635 return UA_STATUSCODE_BADOUTOFMEMORY;
66636 }
66637
66638 (void) memcpy (dest: folderPath, src: ctx->trustListFolder.data,
66639 n: ctx->trustListFolder.length);
66640 folderPath[ctx->trustListFolder.length] = 0;
66641 numCertificates = scandir(dir: folderPath, namelist: &dirlist,
66642 selector: UA_Certificate_Filter_der_pem,
66643 cmp: alphasort);
66644 for (i = 0; i < numCertificates; i++) {
66645 if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name,
66646 PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) {
66647 continue;
66648 }
66649 ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert);
66650 if (ret != UA_STATUSCODE_GOOD) {
66651 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66652 msg: "Failed to load the certificate file %s", certFile);
66653 continue; /* continue or return ? */
66654 }
66655 if (UA_skTrusted_Cert2X509 (certificateTrustList: &strCert, certificateTrustListSize: 1, ctx) != UA_STATUSCODE_GOOD) {
66656 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66657 msg: "Failed to decode the certificate file %s", certFile);
66658 UA_ByteString_clear (p: &strCert);
66659 continue; /* continue or return ? */
66660 }
66661 UA_ByteString_clear (p: &strCert);
66662 }
66663 }
66664
66665 if (ctx->issuerListFolder.length > 0) {
66666 UA_LOG_INFO(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the issuer-list");
66667
66668 sk_X509_pop_free (ctx->skIssue, X509_free);
66669 ctx->skIssue = sk_X509_new_null();
66670 if (ctx->skIssue == NULL) {
66671 return UA_STATUSCODE_BADOUTOFMEMORY;
66672 }
66673
66674 memcpy (dest: folderPath, src: ctx->issuerListFolder.data, n: ctx->issuerListFolder.length);
66675 folderPath[ctx->issuerListFolder.length] = 0;
66676 numCertificates = scandir(dir: folderPath, namelist: &dirlist,
66677 selector: UA_Certificate_Filter_der_pem,
66678 cmp: alphasort);
66679 for (i = 0; i < numCertificates; i++) {
66680 if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name,
66681 PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) {
66682 continue;
66683 }
66684 ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert);
66685 if (ret != UA_STATUSCODE_GOOD) {
66686 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66687 msg: "Failed to load the certificate file %s", certFile);
66688 continue; /* continue or return ? */
66689 }
66690 if (UA_skIssuer_Cert2X509 (certificateIssuerList: &strCert, certificateIssuerListSize: 1, ctx) != UA_STATUSCODE_GOOD) {
66691 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66692 msg: "Failed to decode the certificate file %s", certFile);
66693 UA_ByteString_clear (p: &strCert);
66694 continue; /* continue or return ? */
66695 }
66696 UA_ByteString_clear (p: &strCert);
66697 }
66698 }
66699
66700 if (ctx->revocationListFolder.length > 0) {
66701 UA_LOG_INFO(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the revocation-list");
66702
66703 sk_X509_CRL_pop_free (ctx->skCrls, X509_CRL_free);
66704 ctx->skCrls = sk_X509_CRL_new_null();
66705 if (ctx->skCrls == NULL) {
66706 return UA_STATUSCODE_BADOUTOFMEMORY;
66707 }
66708
66709 memcpy (dest: folderPath, src: ctx->revocationListFolder.data, n: ctx->revocationListFolder.length);
66710 folderPath[ctx->revocationListFolder.length] = 0;
66711 numCertificates = scandir(dir: folderPath, namelist: &dirlist,
66712 selector: UA_Certificate_Filter_crl,
66713 cmp: alphasort);
66714 for (i = 0; i < numCertificates; i++) {
66715 if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name,
66716 PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) {
66717 continue;
66718 }
66719 ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert);
66720 if (ret != UA_STATUSCODE_GOOD) {
66721 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66722 msg: "Failed to load the revocation file %s", certFile);
66723 continue; /* continue or return ? */
66724 }
66725 if (UA_skCrls_Cert2X509 (certificateRevocationList: &strCert, certificateRevocationListSize: 1, ctx) != UA_STATUSCODE_GOOD) {
66726 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66727 msg: "Failed to decode the revocation file %s", certFile);
66728 UA_ByteString_clear (p: &strCert);
66729 continue; /* continue or return ? */
66730 }
66731 UA_ByteString_clear (p: &strCert);
66732 }
66733 }
66734
66735 ret = UA_STATUSCODE_GOOD;
66736 return ret;
66737}
66738
66739#endif /* end of __linux__ */
66740
66741static UA_StatusCode
66742UA_X509_Store_CTX_Error_To_UAError (int opensslErr) {
66743 UA_StatusCode ret;
66744
66745 switch (opensslErr) {
66746 case X509_V_ERR_CERT_HAS_EXPIRED:
66747 case X509_V_ERR_CERT_NOT_YET_VALID:
66748 case X509_V_ERR_CRL_NOT_YET_VALID:
66749 case X509_V_ERR_CRL_HAS_EXPIRED:
66750 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
66751 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
66752 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
66753 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
66754 ret = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
66755 break;
66756 case X509_V_ERR_CERT_REVOKED:
66757 ret = UA_STATUSCODE_BADCERTIFICATEREVOKED;
66758 break;
66759 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
66760 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
66761 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
66762 ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
66763 break;
66764 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
66765 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
66766 ret = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
66767 break;
66768 case X509_V_ERR_UNABLE_TO_GET_CRL:
66769 ret = UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN;
66770 break;
66771 default:
66772 ret = UA_STATUSCODE_BADCERTIFICATEINVALID;
66773 break;
66774 }
66775 return ret;
66776 }
66777
66778static UA_StatusCode
66779UA_CertificateVerification_Verify (void * verificationContext,
66780 const UA_ByteString * certificate) {
66781 X509_STORE_CTX* storeCtx;
66782 X509_STORE* store;
66783 CertContext * ctx;
66784 UA_StatusCode ret;
66785 int opensslRet;
66786 X509 * certificateX509 = NULL;
66787
66788 if (verificationContext == NULL) {
66789 return UA_STATUSCODE_BADINTERNALERROR;
66790 }
66791 ctx = (CertContext *) verificationContext;
66792
66793 store = X509_STORE_new();
66794 storeCtx = X509_STORE_CTX_new();
66795
66796 if (store == NULL || storeCtx == NULL) {
66797 ret = UA_STATUSCODE_BADOUTOFMEMORY;
66798 goto cleanup;
66799 }
66800#ifdef __linux__
66801 ret = UA_ReloadCertFromFolder (ctx);
66802 if (ret != UA_STATUSCODE_GOOD) {
66803 goto cleanup;
66804 }
66805#endif
66806
66807 certificateX509 = UA_OpenSSL_LoadCertificate(certificate);
66808 if (certificateX509 == NULL) {
66809 ret = UA_STATUSCODE_BADCERTIFICATEINVALID;
66810 goto cleanup;
66811 }
66812
66813 X509_STORE_set_flags(ctx: store, flags: 0);
66814 opensslRet = X509_STORE_CTX_init (ctx: storeCtx, trust_store: store, target: certificateX509,
66815 untrusted: ctx->skIssue);
66816 if (opensslRet != 1) {
66817 ret = UA_STATUSCODE_BADINTERNALERROR;
66818 goto cleanup;
66819 }
66820#if defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT < 0x10100000L
66821 (void) X509_STORE_CTX_trusted_stack (storeCtx, ctx->skTrusted);
66822#else
66823 (void) X509_STORE_CTX_set0_trusted_stack (ctx: storeCtx, sk: ctx->skTrusted);
66824#endif
66825
66826 /* Set crls to ctx */
66827 if (sk_X509_CRL_num (ctx->skCrls) > 0) {
66828 X509_STORE_CTX_set0_crls (ctx: storeCtx, sk: ctx->skCrls);
66829 }
66830
66831 /* Set flag to check if the certificate has an invalid signature */
66832 X509_STORE_CTX_set_flags (ctx: storeCtx, X509_V_FLAG_CHECK_SS_SIGNATURE);
66833
66834 if (X509_STORE_CTX_get_check_issued(ctx: storeCtx) (storeCtx,certificateX509, certificateX509) != 1) {
66835 X509_STORE_CTX_set_flags (ctx: storeCtx, X509_V_FLAG_CRL_CHECK);
66836 }
66837
66838 /* This condition will check whether the certificate is a User certificate or a CA certificate.
66839 * If the KU_KEY_CERT_SIGN and KU_CRL_SIGN of key_usage are set, then the certificate shall be
66840 * condidered as CA Certificate and cannot be used to establish a connection. Refer the test case
66841 * CTT/Security/Security Certificate Validation/029.js for more details */
66842 /** \todo Can the ca-parameter of X509_check_purpose can be used? */
66843 if(X509_check_purpose(x: certificateX509, X509_PURPOSE_CRL_SIGN, ca: 0) && X509_check_ca(x: certificateX509)) {
66844 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
66845 }
66846
66847 opensslRet = X509_verify_cert (ctx: storeCtx);
66848 if (opensslRet == 1) {
66849 ret = UA_STATUSCODE_GOOD;
66850
66851 /* Check if the not trusted certificate has a CRL file. If there is no CRL file available for the corresponding
66852 * parent certificate then return status code UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN. Refer the test
66853 * case CTT/Security/Security Certificate Validation/002.js */
66854 if (X509_STORE_CTX_get_check_issued (ctx: storeCtx) (storeCtx,certificateX509, certificateX509) != 1) {
66855 /* Free X509_STORE_CTX and reuse it for certification verification */
66856 if (storeCtx != NULL) {
66857 X509_STORE_CTX_free(ctx: storeCtx);
66858 }
66859
66860 /* Initialised X509_STORE_CTX sructure*/
66861 storeCtx = X509_STORE_CTX_new();
66862
66863 /* Sets up X509_STORE_CTX structure for a subsequent verification operation */
66864 X509_STORE_set_flags(ctx: store, flags: 0);
66865 X509_STORE_CTX_init (ctx: storeCtx, trust_store: store, target: certificateX509,untrusted: ctx->skIssue);
66866
66867 /* Set trust list to ctx */
66868 (void) X509_STORE_CTX_trusted_stack (ctx: storeCtx, sk: ctx->skTrusted);
66869
66870 /* Set crls to ctx */
66871 X509_STORE_CTX_set0_crls (ctx: storeCtx, sk: ctx->skCrls);
66872
66873 /* Set flags for CRL check */
66874 X509_STORE_CTX_set_flags (ctx: storeCtx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
66875
66876 opensslRet = X509_verify_cert (ctx: storeCtx);
66877 if (opensslRet != 1) {
66878 opensslRet = X509_STORE_CTX_get_error (ctx: storeCtx);
66879 if (opensslRet == X509_V_ERR_UNABLE_TO_GET_CRL) {
66880 ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN;
66881 }
66882 }
66883 }
66884 }
66885 else {
66886 opensslRet = X509_STORE_CTX_get_error (ctx: storeCtx);
66887
66888 /* Check the issued certificate of a CA that is not trusted but available */
66889 if(opensslRet == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN){
66890 int trusted_cert_len = sk_X509_num(ctx->skTrusted);
66891 int cmpVal;
66892 X509 *trusted_cert;
66893 const ASN1_OCTET_STRING *trusted_cert_keyid;
66894 const ASN1_OCTET_STRING *remote_cert_keyid;
66895
66896 for (int i = 0; i < trusted_cert_len; i++) {
66897 trusted_cert = sk_X509_value(ctx->skTrusted, i);
66898
66899 /* Fetch the Subject key identifier of the certificate in trust list */
66900 trusted_cert_keyid = X509_get0_subject_key_id(x: trusted_cert);
66901
66902 /* Fetch the Subject key identifier of the remote certificate */
66903 remote_cert_keyid = X509_get0_subject_key_id(x: certificateX509);
66904
66905 /* Check remote certificate is present in the trust list */
66906 cmpVal = ASN1_OCTET_STRING_cmp(a: trusted_cert_keyid, b: remote_cert_keyid);
66907 if (cmpVal == 0){
66908 ret = UA_STATUSCODE_GOOD;
66909 goto cleanup;
66910 }
66911 }
66912 }
66913
66914 /* Return expected OPCUA error code */
66915 ret = UA_X509_Store_CTX_Error_To_UAError (opensslErr: opensslRet);
66916 }
66917cleanup:
66918 if (store != NULL) {
66919 X509_STORE_free (v: store);
66920 }
66921 if (storeCtx != NULL) {
66922 X509_STORE_CTX_free (ctx: storeCtx);
66923 }
66924 if (certificateX509 != NULL) {
66925 X509_free (a: certificateX509);
66926 }
66927 return ret;
66928}
66929
66930static UA_StatusCode
66931UA_CertificateVerification_VerifyApplicationURI (void * verificationContext,
66932 const UA_ByteString * certificate,
66933 const UA_String * applicationURI) {
66934 (void) verificationContext;
66935
66936 const unsigned char * pData;
66937 X509 * certificateX509;
66938 UA_String subjectURI;
66939 GENERAL_NAMES * pNames;
66940 int i;
66941 UA_StatusCode ret;
66942
66943 pData = certificate->data;
66944 if (pData == NULL) {
66945 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
66946 }
66947
66948 certificateX509 = UA_OpenSSL_LoadCertificate(certificate);
66949 if (certificateX509 == NULL) {
66950 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
66951 }
66952
66953 pNames = (GENERAL_NAMES *) X509_get_ext_d2i(x: certificateX509, NID_subject_alt_name,
66954 NULL, NULL);
66955 if (pNames == NULL) {
66956 X509_free (a: certificateX509);
66957 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
66958 }
66959 for (i = 0; i < sk_GENERAL_NAME_num (pNames); i++) {
66960 GENERAL_NAME * value = sk_GENERAL_NAME_value (pNames, i);
66961 if (value->type == GEN_URI) {
66962 subjectURI.length = (size_t) (value->d.ia5->length);
66963 subjectURI.data = (UA_Byte *) UA_malloc (size: subjectURI.length);
66964 if (subjectURI.data == NULL) {
66965 X509_free (a: certificateX509);
66966 sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
66967 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
66968 }
66969 (void) memcpy (dest: subjectURI.data, src: value->d.ia5->data, n: subjectURI.length);
66970 break;
66971 }
66972
66973 }
66974
66975 ret = UA_STATUSCODE_GOOD;
66976 if (UA_Bstrstr (s1: subjectURI.data, l1: subjectURI.length,
66977 s2: applicationURI->data, l2: applicationURI->length) == NULL) {
66978 ret = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
66979 }
66980
66981 X509_free (a: certificateX509);
66982 sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
66983 UA_String_clear (p: &subjectURI);
66984 return ret;
66985}
66986
66987/* main entry */
66988
66989UA_StatusCode
66990UA_CertificateVerification_Trustlist(UA_CertificateVerification * cv,
66991 const UA_ByteString * certificateTrustList,
66992 size_t certificateTrustListSize,
66993 const UA_ByteString * certificateIssuerList,
66994 size_t certificateIssuerListSize,
66995 const UA_ByteString * certificateRevocationList,
66996 size_t certificateRevocationListSize) {
66997 UA_StatusCode ret;
66998
66999 if (cv == NULL) {
67000 return UA_STATUSCODE_BADINTERNALERROR;
67001 }
67002
67003 CertContext * context = (CertContext *) UA_malloc (size: sizeof (CertContext));
67004 if (context == NULL) {
67005 return UA_STATUSCODE_BADOUTOFMEMORY;
67006 }
67007 ret = UA_CertContext_Init (context);
67008 if (ret != UA_STATUSCODE_GOOD) {
67009 return ret;
67010 }
67011
67012 cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI;
67013 cv->clear = UA_CertificateVerification_clear;
67014 cv->context = context;
67015 cv->verifyCertificate = UA_CertificateVerification_Verify;
67016
67017 if (certificateTrustListSize > 0) {
67018 if (UA_skTrusted_Cert2X509 (certificateTrustList, certificateTrustListSize,
67019 ctx: context) != UA_STATUSCODE_GOOD) {
67020 ret = UA_STATUSCODE_BADINTERNALERROR;
67021 goto errout;
67022 }
67023 }
67024
67025 if (certificateIssuerListSize > 0) {
67026 if (UA_skIssuer_Cert2X509 (certificateIssuerList, certificateIssuerListSize,
67027 ctx: context) != UA_STATUSCODE_GOOD) {
67028 ret = UA_STATUSCODE_BADINTERNALERROR;
67029 goto errout;
67030 }
67031 }
67032
67033 if (certificateRevocationListSize > 0) {
67034 if (UA_skCrls_Cert2X509 (certificateRevocationList, certificateRevocationListSize,
67035 ctx: context) != UA_STATUSCODE_GOOD) {
67036 ret = UA_STATUSCODE_BADINTERNALERROR;
67037 goto errout;
67038 }
67039 }
67040
67041 return UA_STATUSCODE_GOOD;
67042
67043errout:
67044 UA_CertificateVerification_clear (cv);
67045 return ret;
67046}
67047
67048#ifdef __linux__ /* Linux only so far */
67049UA_StatusCode
67050UA_CertificateVerification_CertFolders(UA_CertificateVerification * cv,
67051 const char * trustListFolder,
67052 const char * issuerListFolder,
67053 const char * revocationListFolder) {
67054 UA_StatusCode ret;
67055 if (cv == NULL) {
67056 return UA_STATUSCODE_BADINTERNALERROR;
67057 }
67058
67059 CertContext * context = (CertContext *) UA_malloc (size: sizeof (CertContext));
67060 if (context == NULL) {
67061 return UA_STATUSCODE_BADOUTOFMEMORY;
67062 }
67063 ret = UA_CertContext_Init (context);
67064 if (ret != UA_STATUSCODE_GOOD) {
67065 return ret;
67066 }
67067
67068 cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI;
67069 cv->clear = UA_CertificateVerification_clear;
67070 cv->context = context;
67071 cv->verifyCertificate = UA_CertificateVerification_Verify;
67072
67073 /* Only set the folder paths. They will be reloaded during runtime. */
67074
67075 context->trustListFolder = UA_STRING_ALLOC(trustListFolder);
67076 context->issuerListFolder = UA_STRING_ALLOC(issuerListFolder);
67077 context->revocationListFolder = UA_STRING_ALLOC(revocationListFolder);
67078
67079 return UA_STATUSCODE_GOOD;
67080}
67081#endif
67082
67083#endif /* end of defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
67084
67085/**** amalgamated original file "/plugins/crypto/mbedtls/securitypolicy_mbedtls_common.h" ****/
67086
67087/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
67088 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
67089 *
67090 * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
67091 */
67092
67093
67094
67095#if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_PUBSUB_ENCRYPTION)
67096
67097#include <mbedtls/md.h>
67098#include <mbedtls/x509_crt.h>
67099#include <mbedtls/ctr_drbg.h>
67100
67101// MBEDTLS_ENTROPY_HARDWARE_ALT should be defined if your hardware does not supportd platform entropy
67102
67103#define UA_SHA1_LENGTH 20
67104
67105_UA_BEGIN_DECLS
67106
67107void
67108swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB);
67109
67110void
67111mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
67112 const UA_ByteString *in, unsigned char *out);
67113
67114UA_StatusCode
67115mbedtls_generateKey(mbedtls_md_context_t *context,
67116 const UA_ByteString *secret, const UA_ByteString *seed,
67117 UA_ByteString *out);
67118
67119UA_StatusCode
67120mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message,
67121 const UA_ByteString *signature);
67122
67123UA_StatusCode
67124mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey,
67125 mbedtls_ctr_drbg_context *drbgContext,
67126 const UA_ByteString *message,
67127 UA_ByteString *signature);
67128
67129UA_StatusCode
67130mbedtls_thumbprint_sha1(const UA_ByteString *certificate,
67131 UA_ByteString *thumbprint);
67132
67133/* Set the hashing scheme before calling
67134 * E.g. mbedtls_rsa_set_padding(context, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); */
67135UA_StatusCode
67136mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context,
67137 mbedtls_ctr_drbg_context *drbgContext,
67138 UA_ByteString *data, const size_t plainTextBlockSize);
67139
67140UA_StatusCode
67141mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey,
67142 mbedtls_ctr_drbg_context *drbgContext,
67143 UA_ByteString *data);
67144
67145int UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target, void *p_rng);
67146
67147UA_StatusCode UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData, UA_ByteString *target);
67148
67149UA_ByteString UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data);
67150
67151_UA_END_DECLS
67152
67153#endif
67154
67155
67156/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic128rsa15.c" ****/
67157
67158/* This Source Code Form is subject to the terms of the Mozilla Public
67159 * License, v. 2.0. If a copy of the MPL was not distributed with this
67160 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
67161 *
67162 * Copyright 2018-2019 (c) Mark Giraud, Fraunhofer IOSB
67163 * Copyright 2019 (c) Kalycito Infotech Private Limited
67164 * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green)
67165 * Copyright 2020 (c) Wind River Systems, Inc.
67166 * Copyright 2020 (c) basysKom GmbH
67167 *
67168 */
67169
67170
67171#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
67172
67173
67174#include <mbedtls/aes.h>
67175#include <mbedtls/ctr_drbg.h>
67176#include <mbedtls/entropy.h>
67177#include <mbedtls/error.h>
67178#include <mbedtls/md.h>
67179#include <mbedtls/sha1.h>
67180#include <mbedtls/version.h>
67181#include <mbedtls/x509_crt.h>
67182
67183/* Notes:
67184 * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to
67185 * allocate temp buffers.
67186 * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
67187 */
67188
67189#define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11
67190#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH 16
67191#define UA_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH 16
67192#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE 16
67193#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE 16
67194#define UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH 128
67195#define UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH 512
67196
67197typedef struct {
67198 UA_ByteString localCertThumbprint;
67199
67200 mbedtls_ctr_drbg_context drbgContext;
67201 mbedtls_entropy_context entropyContext;
67202 mbedtls_md_context_t sha1MdContext;
67203 mbedtls_pk_context localPrivateKey;
67204} Basic128Rsa15_PolicyContext;
67205
67206typedef struct {
67207 Basic128Rsa15_PolicyContext *policyContext;
67208
67209 UA_ByteString localSymSigningKey;
67210 UA_ByteString localSymEncryptingKey;
67211 UA_ByteString localSymIv;
67212
67213 UA_ByteString remoteSymSigningKey;
67214 UA_ByteString remoteSymEncryptingKey;
67215 UA_ByteString remoteSymIv;
67216
67217 mbedtls_x509_crt remoteCertificate;
67218} Basic128Rsa15_ChannelContext;
67219
67220/********************/
67221/* AsymmetricModule */
67222/********************/
67223
67224static UA_StatusCode
67225asym_verify_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67226 const UA_ByteString *message,
67227 const UA_ByteString *signature) {
67228 if(message == NULL || signature == NULL || cc == NULL)
67229 return UA_STATUSCODE_BADINTERNALERROR;
67230
67231 return mbedtls_verifySig_sha1(&cc->remoteCertificate, message, signature);
67232}
67233
67234static UA_StatusCode
67235asym_sign_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67236 const UA_ByteString *message,
67237 UA_ByteString *signature) {
67238 if(message == NULL || signature == NULL || cc == NULL)
67239 return UA_STATUSCODE_BADINTERNALERROR;
67240
67241 Basic128Rsa15_PolicyContext *pc = cc->policyContext;
67242 return mbedtls_sign_sha1(&pc->localPrivateKey, &pc->drbgContext,
67243 message, signature);
67244}
67245
67246static size_t
67247asym_getLocalSignatureSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67248 if(cc == NULL)
67249 return 0;
67250#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67251 return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
67252#else
67253 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
67254#endif
67255
67256
67257}
67258
67259static size_t
67260asym_getRemoteSignatureSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67261 if(cc == NULL)
67262 return 0;
67263
67264#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67265 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
67266#else
67267 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
67268#endif
67269
67270}
67271
67272static UA_StatusCode
67273asym_encrypt_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67274 UA_ByteString *data) {
67275 if(cc == NULL || data == NULL)
67276 return UA_STATUSCODE_BADINTERNALERROR;
67277
67278 mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67279 mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
67280
67281#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67282 size_t plainTextBlockSize = remoteRsaContext->len - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
67283#else
67284 size_t keylen = mbedtls_rsa_get_len(remoteRsaContext);
67285 size_t plainTextBlockSize = mbedtls_rsa_get_len(remoteRsaContext) -
67286 UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
67287#endif
67288
67289 if(data->length % plainTextBlockSize != 0)
67290 return UA_STATUSCODE_BADINTERNALERROR;
67291
67292 size_t blocks = data->length / plainTextBlockSize;
67293 UA_ByteString encrypted;
67294#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67295 UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, blocks * remoteRsaContext->len);
67296#else
67297 UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, blocks * keylen);
67298#endif
67299 if(retval != UA_STATUSCODE_GOOD)
67300 return retval;
67301
67302 size_t lenDataToEncrypt = data->length;
67303 size_t inOffset = 0;
67304 size_t offset = 0;
67305 size_t outLength = 0;
67306 Basic128Rsa15_PolicyContext *pc = cc->policyContext;
67307 while(lenDataToEncrypt >= plainTextBlockSize) {
67308 int mbedErr = mbedtls_pk_encrypt(&cc->remoteCertificate.pk,
67309 data->data + inOffset, plainTextBlockSize,
67310 encrypted.data + offset, &outLength,
67311 encrypted.length - offset,
67312 mbedtls_ctr_drbg_random,
67313 &pc->drbgContext);
67314 if(mbedErr) {
67315 UA_ByteString_clear(&encrypted);
67316 return UA_STATUSCODE_BADINTERNALERROR;
67317 }
67318
67319 inOffset += plainTextBlockSize;
67320 offset += outLength;
67321 lenDataToEncrypt -= plainTextBlockSize;
67322 }
67323
67324 memcpy(data->data, encrypted.data, offset);
67325 UA_ByteString_clear(&encrypted);
67326
67327 return UA_STATUSCODE_GOOD;
67328}
67329
67330static UA_StatusCode
67331asym_decrypt_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67332 UA_ByteString *data) {
67333 if(cc == NULL || data == NULL)
67334 return UA_STATUSCODE_BADINTERNALERROR;
67335
67336 Basic128Rsa15_PolicyContext *pc = cc->policyContext;
67337 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey);
67338 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
67339#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67340 size_t keylen = rsaContext->len;
67341#else
67342 size_t keylen = mbedtls_rsa_get_len(rsaContext);
67343#endif
67344 if(data->length % keylen != 0)
67345 return UA_STATUSCODE_BADINTERNALERROR;
67346
67347 size_t inOffset = 0;
67348 size_t outOffset = 0;
67349 size_t outLength = 0;
67350 unsigned char buf[512];
67351
67352 while(inOffset < data->length) {
67353 int mbedErr = mbedtls_pk_decrypt(&pc->localPrivateKey,
67354 data->data + inOffset, keylen,
67355 buf, &outLength, 512,
67356 mbedtls_ctr_drbg_random,
67357 &pc->drbgContext);
67358 if(mbedErr)
67359 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67360
67361 memcpy(data->data + outOffset, buf, outLength);
67362 inOffset += keylen;
67363 outOffset += outLength;
67364 }
67365
67366 data->length = outOffset;
67367 return UA_STATUSCODE_GOOD;
67368}
67369
67370static size_t
67371asym_getLocalEncryptionKeyLength_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67372#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67373 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67374 return rsaContext->len;
67375#else
67376 if(cc == NULL)
67377 return 0;
67378 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
67379#endif
67380}
67381
67382static size_t
67383asym_getRemoteEncryptionKeyLength_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67384 return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
67385}
67386
67387static size_t
67388asym_getRemoteBlockSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67389#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67390 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67391 return rsaContext->len;
67392#else
67393 if(cc == NULL)
67394 return 0;
67395 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
67396#endif
67397}
67398
67399static size_t
67400asym_getRemotePlainTextBlockSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67401#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67402 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67403 return rsaContext->len - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
67404#else
67405 if(cc == NULL)
67406 return 0;
67407 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
67408 UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
67409#endif
67410}
67411
67412static UA_StatusCode
67413asym_makeThumbprint_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
67414 const UA_ByteString *certificate,
67415 UA_ByteString *thumbprint) {
67416 if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
67417 return UA_STATUSCODE_BADINTERNALERROR;
67418 return mbedtls_thumbprint_sha1(certificate, thumbprint);
67419}
67420
67421static UA_StatusCode
67422asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
67423 const UA_ByteString *certificateThumbprint) {
67424 if(securityPolicy == NULL || certificateThumbprint == NULL)
67425 return UA_STATUSCODE_BADINTERNALERROR;
67426
67427 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
67428 if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
67429 return UA_STATUSCODE_BADCERTIFICATEINVALID;
67430
67431 return UA_STATUSCODE_GOOD;
67432}
67433
67434/*******************/
67435/* SymmetricModule */
67436/*******************/
67437
67438static UA_StatusCode
67439sym_verify_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67440 const UA_ByteString *message,
67441 const UA_ByteString *signature) {
67442 if(cc == NULL || message == NULL || signature == NULL)
67443 return UA_STATUSCODE_BADINTERNALERROR;
67444
67445 /* Compute MAC */
67446 if(signature->length != UA_SHA1_LENGTH)
67447 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67448
67449 Basic128Rsa15_PolicyContext *pc = cc->policyContext;
67450
67451 unsigned char mac[UA_SHA1_LENGTH];
67452 mbedtls_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac);
67453
67454 /* Compare with Signature */
67455 if(!UA_constantTimeEqual(signature->data, mac, UA_SHA1_LENGTH))
67456 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67457 return UA_STATUSCODE_GOOD;
67458}
67459
67460static UA_StatusCode
67461sym_sign_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
67462 const UA_ByteString *message,
67463 UA_ByteString *signature) {
67464 if(signature->length != UA_SHA1_LENGTH)
67465 return UA_STATUSCODE_BADINTERNALERROR;
67466
67467 mbedtls_hmac(&cc->policyContext->sha1MdContext, &cc->localSymSigningKey,
67468 message, signature->data);
67469 return UA_STATUSCODE_GOOD;
67470}
67471
67472static size_t
67473sym_getSignatureSize_sp_basic128rsa15(const void *channelContext) {
67474 return UA_SHA1_LENGTH;
67475}
67476
67477static size_t
67478sym_getSigningKeyLength_sp_basic128rsa15(const void *const channelContext) {
67479 return UA_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH;
67480}
67481
67482static size_t
67483sym_getEncryptionKeyLength_sp_basic128rsa15(const void *channelContext) {
67484 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH;
67485}
67486
67487static size_t
67488sym_getEncryptionBlockSize_sp_basic128rsa15(const void *const channelContext) {
67489 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
67490}
67491
67492static size_t
67493sym_getPlainTextBlockSize_sp_basic128rsa15(const void *const channelContext) {
67494 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE;
67495}
67496
67497static UA_StatusCode
67498sym_encrypt_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
67499 UA_ByteString *data) {
67500 if(cc == NULL || data == NULL)
67501 return UA_STATUSCODE_BADINTERNALERROR;
67502
67503 if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE)
67504 return UA_STATUSCODE_BADINTERNALERROR;
67505
67506 size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE;
67507 if(data->length % plainTextBlockSize != 0)
67508 return UA_STATUSCODE_BADINTERNALERROR;
67509
67510 /* Keylength in bits */
67511 unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
67512 mbedtls_aes_context aesContext;
67513 int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
67514 if(mbedErr)
67515 return UA_STATUSCODE_BADINTERNALERROR;
67516
67517 UA_ByteString ivCopy;
67518 UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
67519 if(retval != UA_STATUSCODE_GOOD)
67520 return retval;
67521
67522 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
67523 ivCopy.data, data->data, data->data);
67524 if(mbedErr)
67525 retval = UA_STATUSCODE_BADINTERNALERROR;
67526 UA_ByteString_clear(&ivCopy);
67527 return retval;
67528}
67529
67530static UA_StatusCode
67531sym_decrypt_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
67532 UA_ByteString *data) {
67533 if(cc == NULL || data == NULL)
67534 return UA_STATUSCODE_BADINTERNALERROR;
67535
67536 size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
67537 if(cc->remoteSymIv.length != encryptionBlockSize)
67538 return UA_STATUSCODE_BADINTERNALERROR;
67539
67540 if(data->length % encryptionBlockSize != 0)
67541 return UA_STATUSCODE_BADINTERNALERROR;
67542
67543 unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
67544 mbedtls_aes_context aesContext;
67545 int mbedErr = mbedtls_aes_setkey_dec(&aesContext,
67546 cc->remoteSymEncryptingKey.data, keylength);
67547 if(mbedErr)
67548 return UA_STATUSCODE_BADINTERNALERROR;
67549
67550 UA_ByteString ivCopy;
67551 UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
67552 if(retval != UA_STATUSCODE_GOOD)
67553 return retval;
67554
67555 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
67556 ivCopy.data, data->data, data->data);
67557 if(mbedErr)
67558 retval = UA_STATUSCODE_BADINTERNALERROR;
67559 UA_ByteString_clear(&ivCopy);
67560 return retval;
67561}
67562
67563static UA_StatusCode
67564sym_generateKey_sp_basic128rsa15(void *policyContext, const UA_ByteString *secret,
67565 const UA_ByteString *seed, UA_ByteString *out) {
67566 if(secret == NULL || seed == NULL || out == NULL)
67567 return UA_STATUSCODE_BADINTERNALERROR;
67568 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)policyContext;
67569 return mbedtls_generateKey(&pc->sha1MdContext, secret, seed, out);
67570}
67571
67572static UA_StatusCode
67573sym_generateNonce_sp_basic128rsa15(void *policyContext, UA_ByteString *out) {
67574 if(out == NULL)
67575 return UA_STATUSCODE_BADINTERNALERROR;
67576 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)policyContext;
67577 int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
67578 if(mbedErr)
67579 return UA_STATUSCODE_BADUNEXPECTEDERROR;
67580 return UA_STATUSCODE_GOOD;
67581}
67582
67583/*****************/
67584/* ChannelModule */
67585/*****************/
67586
67587/* Assumes that the certificate has been verified externally */
67588static UA_StatusCode
67589parseRemoteCertificate_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67590 const UA_ByteString *remoteCertificate) {
67591 if(remoteCertificate == NULL || cc == NULL)
67592 return UA_STATUSCODE_BADINTERNALERROR;
67593
67594 /* Parse the certificate */
67595 int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
67596 remoteCertificate->length);
67597 if(mbedErr)
67598 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67599
67600 /* Check the key length */
67601#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67602 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67603 if(rsaContext->len < UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH ||
67604 rsaContext->len > UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH)
67605 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
67606#else
67607 size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
67608 if(keylen < UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH ||
67609 keylen > UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH)
67610 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
67611#endif
67612 return UA_STATUSCODE_GOOD;
67613}
67614
67615static void
67616channelContext_deleteContext_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc) {
67617 UA_ByteString_clear(&cc->localSymSigningKey);
67618 UA_ByteString_clear(&cc->localSymEncryptingKey);
67619 UA_ByteString_clear(&cc->localSymIv);
67620 UA_ByteString_clear(&cc->remoteSymSigningKey);
67621 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
67622 UA_ByteString_clear(&cc->remoteSymIv);
67623 mbedtls_x509_crt_free(&cc->remoteCertificate);
67624 UA_free(cc);
67625}
67626
67627static UA_StatusCode
67628channelContext_newContext_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
67629 const UA_ByteString *remoteCertificate,
67630 void **pp_contextData) {
67631 if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
67632 return UA_STATUSCODE_BADINTERNALERROR;
67633
67634 /* Allocate the channel context */
67635 *pp_contextData = UA_malloc(sizeof(Basic128Rsa15_ChannelContext));
67636 if(*pp_contextData == NULL)
67637 return UA_STATUSCODE_BADOUTOFMEMORY;
67638
67639 Basic128Rsa15_ChannelContext *cc = (Basic128Rsa15_ChannelContext *)*pp_contextData;
67640
67641 /* Initialize the channel context */
67642 cc->policyContext = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
67643
67644 UA_ByteString_init(&cc->localSymSigningKey);
67645 UA_ByteString_init(&cc->localSymEncryptingKey);
67646 UA_ByteString_init(&cc->localSymIv);
67647
67648 UA_ByteString_init(&cc->remoteSymSigningKey);
67649 UA_ByteString_init(&cc->remoteSymEncryptingKey);
67650 UA_ByteString_init(&cc->remoteSymIv);
67651
67652 mbedtls_x509_crt_init(&cc->remoteCertificate);
67653
67654 // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
67655 UA_StatusCode retval = parseRemoteCertificate_sp_basic128rsa15(cc, remoteCertificate);
67656 if(retval != UA_STATUSCODE_GOOD) {
67657 channelContext_deleteContext_sp_basic128rsa15(cc);
67658 *pp_contextData = NULL;
67659 }
67660 return retval;
67661}
67662
67663static UA_StatusCode
67664channelContext_setLocalSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67665 const UA_ByteString *key) {
67666 if(key == NULL || cc == NULL)
67667 return UA_STATUSCODE_BADINTERNALERROR;
67668
67669 UA_ByteString_clear(&cc->localSymEncryptingKey);
67670 return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
67671}
67672
67673static UA_StatusCode
67674channelContext_setLocalSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67675 const UA_ByteString *key) {
67676 if(key == NULL || cc == NULL)
67677 return UA_STATUSCODE_BADINTERNALERROR;
67678
67679 UA_ByteString_clear(&cc->localSymSigningKey);
67680 return UA_ByteString_copy(key, &cc->localSymSigningKey);
67681}
67682
67683
67684static UA_StatusCode
67685channelContext_setLocalSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67686 const UA_ByteString *iv) {
67687 if(iv == NULL || cc == NULL)
67688 return UA_STATUSCODE_BADINTERNALERROR;
67689
67690 UA_ByteString_clear(&cc->localSymIv);
67691 return UA_ByteString_copy(iv, &cc->localSymIv);
67692}
67693
67694static UA_StatusCode
67695channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67696 const UA_ByteString *key) {
67697 if(key == NULL || cc == NULL)
67698 return UA_STATUSCODE_BADINTERNALERROR;
67699
67700 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
67701 return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
67702}
67703
67704static UA_StatusCode
67705channelContext_setRemoteSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67706 const UA_ByteString *key) {
67707 if(key == NULL || cc == NULL)
67708 return UA_STATUSCODE_BADINTERNALERROR;
67709
67710 UA_ByteString_clear(&cc->remoteSymSigningKey);
67711 return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
67712}
67713
67714static UA_StatusCode
67715channelContext_setRemoteSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67716 const UA_ByteString *iv) {
67717 if(iv == NULL || cc == NULL)
67718 return UA_STATUSCODE_BADINTERNALERROR;
67719
67720 UA_ByteString_clear(&cc->remoteSymIv);
67721 return UA_ByteString_copy(iv, &cc->remoteSymIv);
67722}
67723
67724static UA_StatusCode
67725channelContext_compareCertificate_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
67726 const UA_ByteString *certificate) {
67727 if(cc == NULL || certificate == NULL)
67728 return UA_STATUSCODE_BADINTERNALERROR;
67729
67730 mbedtls_x509_crt cert;
67731 mbedtls_x509_crt_init(&cert);
67732 int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
67733 if(mbedErr)
67734 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67735
67736 UA_StatusCode retval = UA_STATUSCODE_GOOD;
67737 if(cert.raw.len != cc->remoteCertificate.raw.len ||
67738 memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
67739 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67740
67741 mbedtls_x509_crt_free(&cert);
67742 return retval;
67743}
67744
67745static void
67746clear_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy) {
67747 if(securityPolicy == NULL)
67748 return;
67749
67750 UA_ByteString_clear(&securityPolicy->localCertificate);
67751
67752 if(securityPolicy->policyContext == NULL)
67753 return;
67754
67755 /* delete all allocated members in the context */
67756 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)
67757 securityPolicy->policyContext;
67758
67759 mbedtls_ctr_drbg_free(&pc->drbgContext);
67760 mbedtls_entropy_free(&pc->entropyContext);
67761 mbedtls_pk_free(&pc->localPrivateKey);
67762 mbedtls_md_free(&pc->sha1MdContext);
67763 UA_ByteString_clear(&pc->localCertThumbprint);
67764
67765 UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
67766 "Deleted members of EndpointContext for sp_basic128rsa15");
67767
67768 UA_free(pc);
67769 securityPolicy->policyContext = NULL;
67770}
67771
67772static UA_StatusCode
67773updateCertificateAndPrivateKey_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy,
67774 const UA_ByteString newCertificate,
67775 const UA_ByteString newPrivateKey) {
67776 if(securityPolicy == NULL)
67777 return UA_STATUSCODE_BADINTERNALERROR;
67778
67779 if(securityPolicy->policyContext == NULL)
67780 return UA_STATUSCODE_BADINTERNALERROR;
67781
67782 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
67783
67784 UA_ByteString_clear(&securityPolicy->localCertificate);
67785
67786 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
67787
67788 if (retval != UA_STATUSCODE_GOOD)
67789 return retval;
67790
67791 /* Set the new private key */
67792 mbedtls_pk_free(&pc->localPrivateKey);
67793 mbedtls_pk_init(&pc->localPrivateKey);
67794 int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
67795 if(mbedErr) {
67796 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67797 goto error;
67798 }
67799
67800 retval = asym_makeThumbprint_sp_basic128rsa15(securityPolicy,
67801 &securityPolicy->localCertificate,
67802 &pc->localCertThumbprint);
67803 if(retval != UA_STATUSCODE_GOOD)
67804 goto error;
67805
67806 return retval;
67807
67808 error:
67809 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
67810 "Could not update certificate and private key");
67811 if(securityPolicy->policyContext != NULL)
67812 clear_sp_basic128rsa15(securityPolicy);
67813 return retval;
67814}
67815
67816static UA_StatusCode
67817policyContext_newContext_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy,
67818 const UA_ByteString localPrivateKey) {
67819 UA_StatusCode retval = UA_STATUSCODE_GOOD;
67820 if(securityPolicy == NULL)
67821 return UA_STATUSCODE_BADINTERNALERROR;
67822
67823 if (localPrivateKey.length == 0) {
67824 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
67825 "Can not initialize security policy. Private key is empty.");
67826 return UA_STATUSCODE_BADINVALIDARGUMENT;
67827 }
67828
67829 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)
67830 UA_malloc(sizeof(Basic128Rsa15_PolicyContext));
67831 securityPolicy->policyContext = (void *)pc;
67832 if(!pc) {
67833 retval = UA_STATUSCODE_BADOUTOFMEMORY;
67834 goto error;
67835 }
67836
67837 /* Initialize the PolicyContext */
67838 memset(pc, 0, sizeof(Basic128Rsa15_PolicyContext));
67839 mbedtls_ctr_drbg_init(&pc->drbgContext);
67840 mbedtls_entropy_init(&pc->entropyContext);
67841 mbedtls_pk_init(&pc->localPrivateKey);
67842 mbedtls_md_init(&pc->sha1MdContext);
67843
67844 /* Initialized the message digest */
67845 const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
67846 int mbedErr = mbedtls_md_setup(&pc->sha1MdContext, mdInfo, MBEDTLS_MD_SHA1);
67847 if(mbedErr) {
67848 retval = UA_STATUSCODE_BADOUTOFMEMORY;
67849 goto error;
67850 }
67851
67852 mbedErr = mbedtls_entropy_self_test(0);
67853
67854 if(mbedErr) {
67855 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67856 goto error;
67857 }
67858
67859 /* Seed the RNG */
67860 char *personalization = "open62541-drbg";
67861 mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
67862 &pc->entropyContext,
67863 (const unsigned char *)personalization, 14);
67864 if(mbedErr) {
67865 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67866 goto error;
67867 }
67868
67869 /* Set the private key */
67870 mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
67871
67872 if(mbedErr) {
67873 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67874 goto error;
67875 }
67876
67877 /* Set the local certificate thumbprint */
67878 retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
67879 if(retval != UA_STATUSCODE_GOOD)
67880 goto error;
67881 retval = asym_makeThumbprint_sp_basic128rsa15(securityPolicy,
67882 &securityPolicy->localCertificate,
67883 &pc->localCertThumbprint);
67884 if(retval != UA_STATUSCODE_GOOD)
67885 goto error;
67886
67887 return UA_STATUSCODE_GOOD;
67888
67889error:
67890 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
67891 "Could not create securityContext: %s", UA_StatusCode_name(retval));
67892 if(securityPolicy->policyContext != NULL)
67893 clear_sp_basic128rsa15(securityPolicy);
67894 return retval;
67895}
67896
67897UA_StatusCode
67898UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
67899 const UA_ByteString localPrivateKey, const UA_Logger *logger) {
67900 memset(policy, 0, sizeof(UA_SecurityPolicy));
67901 policy->logger = logger;
67902
67903 policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0");
67904
67905 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
67906 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
67907 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
67908
67909 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
67910
67911 if (retval != UA_STATUSCODE_GOOD)
67912 return retval;
67913
67914 /* AsymmetricModule */
67915 UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
67916 &asymmetricModule->cryptoModule.signatureAlgorithm;
67917 asym_signatureAlgorithm->uri =
67918 UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
67919 asym_signatureAlgorithm->verify =
67920 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic128rsa15;
67921 asym_signatureAlgorithm->sign =
67922 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic128rsa15;
67923 asym_signatureAlgorithm->getLocalSignatureSize =
67924 (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic128rsa15;
67925 asym_signatureAlgorithm->getRemoteSignatureSize =
67926 (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic128rsa15;
67927 asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
67928 asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
67929
67930 UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
67931 &asymmetricModule->cryptoModule.encryptionAlgorithm;
67932 asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-1_5");
67933 asym_encryptionAlgorithm->encrypt =
67934 (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic128rsa15;
67935 asym_encryptionAlgorithm->decrypt =
67936 (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_basic128rsa15;
67937 asym_encryptionAlgorithm->getLocalKeyLength =
67938 (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic128rsa15;
67939 asym_encryptionAlgorithm->getRemoteKeyLength =
67940 (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic128rsa15;
67941 asym_encryptionAlgorithm->getRemoteBlockSize =
67942 (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic128rsa15;
67943 asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
67944 (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic128rsa15;
67945
67946 asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic128rsa15;
67947 asymmetricModule->compareCertificateThumbprint =
67948 asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15;
67949
67950 /* SymmetricModule */
67951 symmetricModule->generateKey = sym_generateKey_sp_basic128rsa15;
67952 symmetricModule->generateNonce = sym_generateNonce_sp_basic128rsa15;
67953
67954 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
67955 &symmetricModule->cryptoModule.signatureAlgorithm;
67956 sym_signatureAlgorithm->uri =
67957 UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
67958 sym_signatureAlgorithm->verify =
67959 (UA_StatusCode (*)(void *, const UA_ByteString *,
67960 const UA_ByteString *))sym_verify_sp_basic128rsa15;
67961 sym_signatureAlgorithm->sign =
67962 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic128rsa15;
67963 sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic128rsa15;
67964 sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic128rsa15;
67965 sym_signatureAlgorithm->getLocalKeyLength =
67966 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic128rsa15;
67967 sym_signatureAlgorithm->getRemoteKeyLength =
67968 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic128rsa15;
67969
67970 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
67971 &symmetricModule->cryptoModule.encryptionAlgorithm;
67972 sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
67973 sym_encryptionAlgorithm->encrypt =
67974 (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic128rsa15;
67975 sym_encryptionAlgorithm->decrypt =
67976 (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic128rsa15;
67977 sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic128rsa15;
67978 sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic128rsa15;
67979 sym_encryptionAlgorithm->getRemoteBlockSize =
67980 (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic128rsa15;
67981 sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
67982 (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic128rsa15;
67983 symmetricModule->secureChannelNonceLength = 16;
67984
67985 // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
67986 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
67987
67988 /* ChannelModule */
67989 channelModule->newContext = channelContext_newContext_sp_basic128rsa15;
67990 channelModule->deleteContext = (void (*)(void *))
67991 channelContext_deleteContext_sp_basic128rsa15;
67992
67993 channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
67994 channelContext_setLocalSymEncryptingKey_sp_basic128rsa15;
67995 channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
67996 channelContext_setLocalSymSigningKey_sp_basic128rsa15;
67997 channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
67998 channelContext_setLocalSymIv_sp_basic128rsa15;
67999
68000 channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68001 channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15;
68002 channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68003 channelContext_setRemoteSymSigningKey_sp_basic128rsa15;
68004 channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
68005 channelContext_setRemoteSymIv_sp_basic128rsa15;
68006
68007 channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
68008 channelContext_compareCertificate_sp_basic128rsa15;
68009
68010 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic128rsa15;
68011 policy->clear = clear_sp_basic128rsa15;
68012
68013 UA_StatusCode res = policyContext_newContext_sp_basic128rsa15(policy, localPrivateKey);
68014 if(res != UA_STATUSCODE_GOOD)
68015 clear_sp_basic128rsa15(policy);
68016
68017 return res;
68018}
68019
68020#endif
68021
68022/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic256.c" ****/
68023
68024/* This Source Code Form is subject to the terms of the Mozilla Public
68025 * License, v. 2.0. If a copy of the MPL was not distributed with this
68026 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
68027 *
68028 * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
68029 * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
68030 * Copyright 2019 (c) Kalycito Infotech Private Limited
68031 * Copyright 2020 (c) Wind River Systems, Inc.
68032 * Copyright 2020 (c) basysKom GmbH
68033 *
68034 */
68035
68036
68037#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
68038
68039
68040#include <mbedtls/aes.h>
68041#include <mbedtls/entropy.h>
68042#include <mbedtls/error.h>
68043#include <mbedtls/sha1.h>
68044#include <mbedtls/version.h>
68045
68046/* Notes:
68047 * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to
68048 * allocate temp buffers.
68049 * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
68050 */
68051
68052#define UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN 42
68053#define UA_SHA1_LENGTH 20
68054#define UA_BASIC256_SYM_SIGNING_KEY_LENGTH 24
68055#define UA_SECURITYPOLICY_BASIC256_SYM_KEY_LENGTH 32
68056#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE 16
68057#define UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
68058#define UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH 128
68059#define UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH 512
68060
68061typedef struct {
68062 UA_ByteString localCertThumbprint;
68063
68064 mbedtls_ctr_drbg_context drbgContext;
68065 mbedtls_entropy_context entropyContext;
68066 mbedtls_md_context_t sha1MdContext;
68067 mbedtls_pk_context localPrivateKey;
68068} Basic256_PolicyContext;
68069
68070typedef struct {
68071 Basic256_PolicyContext *policyContext;
68072
68073 UA_ByteString localSymSigningKey;
68074 UA_ByteString localSymEncryptingKey;
68075 UA_ByteString localSymIv;
68076
68077 UA_ByteString remoteSymSigningKey;
68078 UA_ByteString remoteSymEncryptingKey;
68079 UA_ByteString remoteSymIv;
68080
68081 mbedtls_x509_crt remoteCertificate;
68082} Basic256_ChannelContext;
68083
68084/********************/
68085/* AsymmetricModule */
68086/********************/
68087
68088/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
68089static UA_StatusCode
68090asym_verify_sp_basic256(Basic256_ChannelContext *cc,
68091 const UA_ByteString *message,
68092 const UA_ByteString *signature) {
68093 if(message == NULL || signature == NULL || cc == NULL)
68094 return UA_STATUSCODE_BADINTERNALERROR;
68095
68096 return mbedtls_verifySig_sha1(&cc->remoteCertificate, message, signature);
68097}
68098
68099/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
68100static UA_StatusCode
68101asym_sign_sp_basic256(Basic256_ChannelContext *cc,
68102 const UA_ByteString *message,
68103 UA_ByteString *signature) {
68104 if(message == NULL || signature == NULL || cc == NULL)
68105 return UA_STATUSCODE_BADINTERNALERROR;
68106
68107 Basic256_PolicyContext *pc = cc->policyContext;
68108 return mbedtls_sign_sha1(&pc->localPrivateKey, &pc->drbgContext,
68109 message, signature);
68110}
68111
68112static size_t
68113asym_getLocalSignatureSize_sp_basic256(const Basic256_ChannelContext *cc) {
68114 if(cc == NULL)
68115 return 0;
68116#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68117 return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
68118#else
68119 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
68120
68121#endif
68122}
68123
68124static size_t
68125asym_getRemoteSignatureSize_sp_basic256(const Basic256_ChannelContext *cc) {
68126 if(cc == NULL)
68127 return 0;
68128#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68129 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
68130#else
68131 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
68132#endif
68133}
68134
68135static size_t
68136asym_getRemotePlainTextBlockSize_sp_basic256(const Basic256_ChannelContext *cc) {
68137#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68138 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68139 return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
68140#else
68141 if(cc == NULL)
68142 return 0;
68143 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
68144 UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
68145#endif
68146}
68147
68148/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
68149static UA_StatusCode
68150asym_encrypt_sp_basic256(Basic256_ChannelContext *cc,
68151 UA_ByteString *data) {
68152 if(cc == NULL || data == NULL)
68153 return UA_STATUSCODE_BADINTERNALERROR;
68154
68155 const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_basic256(cc);
68156
68157 mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68158 mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
68159
68160 return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext,
68161 data, plainTextBlockSize);
68162}
68163
68164/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
68165static UA_StatusCode
68166asym_decrypt_sp_basic256(Basic256_ChannelContext *cc,
68167 UA_ByteString *data) {
68168 if(cc == NULL || data == NULL)
68169 return UA_STATUSCODE_BADINTERNALERROR;
68170 return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
68171 &cc->policyContext->drbgContext, data);
68172}
68173
68174static size_t
68175asym_getLocalEncryptionKeyLength_sp_basic256(const Basic256_ChannelContext *cc) {
68176 return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
68177}
68178
68179static size_t
68180asym_getRemoteEncryptionKeyLength_sp_basic256(const Basic256_ChannelContext *cc) {
68181 return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
68182}
68183
68184static size_t
68185asym_getRemoteBlockSize_sp_basic256(const Basic256_ChannelContext *cc) {
68186#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68187 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68188 return rsaContext->len;
68189#else
68190 if(cc == NULL)
68191 return 0;
68192 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
68193#endif
68194}
68195
68196static UA_StatusCode
68197asym_makeThumbprint_sp_basic256(const UA_SecurityPolicy *securityPolicy,
68198 const UA_ByteString *certificate,
68199 UA_ByteString *thumbprint) {
68200 if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
68201 return UA_STATUSCODE_BADINTERNALERROR;
68202 return mbedtls_thumbprint_sha1(certificate, thumbprint);
68203}
68204
68205static UA_StatusCode
68206asymmetricModule_compareCertificateThumbprint_sp_basic256(const UA_SecurityPolicy *securityPolicy,
68207 const UA_ByteString *certificateThumbprint) {
68208 if(securityPolicy == NULL || certificateThumbprint == NULL)
68209 return UA_STATUSCODE_BADINTERNALERROR;
68210
68211 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)securityPolicy->policyContext;
68212 if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
68213 return UA_STATUSCODE_BADCERTIFICATEINVALID;
68214
68215 return UA_STATUSCODE_GOOD;
68216}
68217
68218/*******************/
68219/* SymmetricModule */
68220/*******************/
68221
68222static UA_StatusCode
68223sym_verify_sp_basic256(Basic256_ChannelContext *cc,
68224 const UA_ByteString *message,
68225 const UA_ByteString *signature) {
68226 if(cc == NULL || message == NULL || signature == NULL)
68227 return UA_STATUSCODE_BADINTERNALERROR;
68228
68229 /* Compute MAC */
68230 if(signature->length != UA_SHA1_LENGTH)
68231 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68232
68233 Basic256_PolicyContext *pc = cc->policyContext;
68234
68235 unsigned char mac[UA_SHA1_LENGTH];
68236 mbedtls_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac);
68237
68238 /* Compare with Signature */
68239 if(!UA_constantTimeEqual(signature->data, mac, UA_SHA1_LENGTH))
68240 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68241 return UA_STATUSCODE_GOOD;
68242}
68243
68244static UA_StatusCode
68245sym_sign_sp_basic256(const Basic256_ChannelContext *cc,
68246 const UA_ByteString *message, UA_ByteString *signature) {
68247 if(signature->length != UA_SHA1_LENGTH)
68248 return UA_STATUSCODE_BADINTERNALERROR;
68249
68250 mbedtls_hmac(&cc->policyContext->sha1MdContext, &cc->localSymSigningKey,
68251 message, signature->data);
68252 return UA_STATUSCODE_GOOD;
68253}
68254
68255static size_t
68256sym_getSignatureSize_sp_basic256(const void *channelContext) {
68257 return UA_SHA1_LENGTH;
68258}
68259
68260static size_t
68261sym_getSigningKeyLength_sp_basic256(const void *const channelContext) {
68262 return UA_BASIC256_SYM_SIGNING_KEY_LENGTH;
68263}
68264
68265static size_t
68266sym_getEncryptionKeyLength_sp_basic256(const void *channelContext) {
68267 return UA_SECURITYPOLICY_BASIC256_SYM_KEY_LENGTH;
68268}
68269
68270static size_t
68271sym_getEncryptionBlockSize_sp_basic256(const void *const channelContext) {
68272 return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
68273}
68274
68275static size_t
68276sym_getPlainTextBlockSize_sp_basic256(const void *const channelContext) {
68277 return UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE;
68278}
68279
68280static UA_StatusCode
68281sym_encrypt_sp_basic256(const Basic256_ChannelContext *cc,
68282 UA_ByteString *data) {
68283 if(cc == NULL || data == NULL)
68284 return UA_STATUSCODE_BADINTERNALERROR;
68285
68286 if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE)
68287 return UA_STATUSCODE_BADINTERNALERROR;
68288
68289 size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE;
68290 if(data->length % plainTextBlockSize != 0)
68291 return UA_STATUSCODE_BADINTERNALERROR;
68292
68293 /* Keylength in bits */
68294 unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
68295 mbedtls_aes_context aesContext;
68296 int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
68297 if(mbedErr)
68298 return UA_STATUSCODE_BADINTERNALERROR;
68299
68300 UA_ByteString ivCopy;
68301 UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
68302 if(retval != UA_STATUSCODE_GOOD)
68303 return retval;
68304
68305 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
68306 ivCopy.data, data->data, data->data);
68307 if(mbedErr)
68308 retval = UA_STATUSCODE_BADINTERNALERROR;
68309 UA_ByteString_clear(&ivCopy);
68310 return retval;
68311}
68312
68313static UA_StatusCode
68314sym_decrypt_sp_basic256(const Basic256_ChannelContext *cc,
68315 UA_ByteString *data) {
68316 if(cc == NULL || data == NULL)
68317 return UA_STATUSCODE_BADINTERNALERROR;
68318
68319 size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
68320 if(cc->remoteSymIv.length != encryptionBlockSize)
68321 return UA_STATUSCODE_BADINTERNALERROR;
68322
68323 if(data->length % encryptionBlockSize != 0)
68324 return UA_STATUSCODE_BADINTERNALERROR;
68325
68326 unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
68327 mbedtls_aes_context aesContext;
68328 int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength);
68329 if(mbedErr)
68330 return UA_STATUSCODE_BADINTERNALERROR;
68331
68332 UA_ByteString ivCopy;
68333 UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
68334 if(retval != UA_STATUSCODE_GOOD)
68335 return retval;
68336
68337 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
68338 ivCopy.data, data->data, data->data);
68339 if(mbedErr)
68340 retval = UA_STATUSCODE_BADINTERNALERROR;
68341 UA_ByteString_clear(&ivCopy);
68342 return retval;
68343}
68344
68345static UA_StatusCode
68346sym_generateKey_sp_basic256(void *policyContext, const UA_ByteString *secret,
68347 const UA_ByteString *seed, UA_ByteString *out) {
68348 if(secret == NULL || seed == NULL || out == NULL)
68349 return UA_STATUSCODE_BADINTERNALERROR;
68350 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)policyContext;
68351 return mbedtls_generateKey(&pc->sha1MdContext, secret, seed, out);
68352}
68353
68354static UA_StatusCode
68355sym_generateNonce_sp_basic256(void *policyContext, UA_ByteString *out) {
68356 if(out == NULL)
68357 return UA_STATUSCODE_BADINTERNALERROR;
68358 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)policyContext;
68359 int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
68360 if(mbedErr)
68361 return UA_STATUSCODE_BADUNEXPECTEDERROR;
68362 return UA_STATUSCODE_GOOD;
68363}
68364
68365/*****************/
68366/* ChannelModule */
68367/*****************/
68368
68369/* Assumes that the certificate has been verified externally */
68370static UA_StatusCode
68371parseRemoteCertificate_sp_basic256(Basic256_ChannelContext *cc,
68372 const UA_ByteString *remoteCertificate) {
68373 if(remoteCertificate == NULL || cc == NULL)
68374 return UA_STATUSCODE_BADINTERNALERROR;
68375
68376 /* Parse the certificate */
68377 int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
68378 remoteCertificate->length);
68379 if(mbedErr)
68380 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68381
68382 /* Check the key length */
68383#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68384 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68385 if(rsaContext->len < UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH ||
68386 rsaContext->len > UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH)
68387#else
68388 size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
68389 if(keylen < UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH ||
68390 keylen > UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH)
68391#endif
68392 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
68393
68394 return UA_STATUSCODE_GOOD;
68395}
68396
68397static void
68398channelContext_deleteContext_sp_basic256(Basic256_ChannelContext *cc) {
68399 UA_ByteString_clear(&cc->localSymSigningKey);
68400 UA_ByteString_clear(&cc->localSymEncryptingKey);
68401 UA_ByteString_clear(&cc->localSymIv);
68402
68403 UA_ByteString_clear(&cc->remoteSymSigningKey);
68404 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
68405 UA_ByteString_clear(&cc->remoteSymIv);
68406
68407 mbedtls_x509_crt_free(&cc->remoteCertificate);
68408
68409 UA_free(cc);
68410}
68411
68412static UA_StatusCode
68413channelContext_newContext_sp_basic256(const UA_SecurityPolicy *securityPolicy,
68414 const UA_ByteString *remoteCertificate,
68415 void **pp_contextData) {
68416 if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
68417 return UA_STATUSCODE_BADINTERNALERROR;
68418
68419 /* Allocate the channel context */
68420 *pp_contextData = UA_malloc(sizeof(Basic256_ChannelContext));
68421 if(*pp_contextData == NULL)
68422 return UA_STATUSCODE_BADOUTOFMEMORY;
68423
68424 Basic256_ChannelContext *cc = (Basic256_ChannelContext *)*pp_contextData;
68425
68426 /* Initialize the channel context */
68427 cc->policyContext = (Basic256_PolicyContext *)securityPolicy->policyContext;
68428
68429 UA_ByteString_init(&cc->localSymSigningKey);
68430 UA_ByteString_init(&cc->localSymEncryptingKey);
68431 UA_ByteString_init(&cc->localSymIv);
68432
68433 UA_ByteString_init(&cc->remoteSymSigningKey);
68434 UA_ByteString_init(&cc->remoteSymEncryptingKey);
68435 UA_ByteString_init(&cc->remoteSymIv);
68436
68437 mbedtls_x509_crt_init(&cc->remoteCertificate);
68438
68439 // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
68440 UA_StatusCode retval = parseRemoteCertificate_sp_basic256(cc, remoteCertificate);
68441 if(retval != UA_STATUSCODE_GOOD) {
68442 channelContext_deleteContext_sp_basic256(cc);
68443 *pp_contextData = NULL;
68444 }
68445 return retval;
68446}
68447
68448static UA_StatusCode
68449channelContext_setLocalSymEncryptingKey_sp_basic256(Basic256_ChannelContext *cc,
68450 const UA_ByteString *key) {
68451 if(key == NULL || cc == NULL)
68452 return UA_STATUSCODE_BADINTERNALERROR;
68453
68454 UA_ByteString_clear(&cc->localSymEncryptingKey);
68455 return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
68456}
68457
68458static UA_StatusCode
68459channelContext_setLocalSymSigningKey_sp_basic256(Basic256_ChannelContext *cc,
68460 const UA_ByteString *key) {
68461 if(key == NULL || cc == NULL)
68462 return UA_STATUSCODE_BADINTERNALERROR;
68463
68464 UA_ByteString_clear(&cc->localSymSigningKey);
68465 return UA_ByteString_copy(key, &cc->localSymSigningKey);
68466}
68467
68468
68469static UA_StatusCode
68470channelContext_setLocalSymIv_sp_basic256(Basic256_ChannelContext *cc,
68471 const UA_ByteString *iv) {
68472 if(iv == NULL || cc == NULL)
68473 return UA_STATUSCODE_BADINTERNALERROR;
68474
68475 UA_ByteString_clear(&cc->localSymIv);
68476 return UA_ByteString_copy(iv, &cc->localSymIv);
68477}
68478
68479static UA_StatusCode
68480channelContext_setRemoteSymEncryptingKey_sp_basic256(Basic256_ChannelContext *cc,
68481 const UA_ByteString *key) {
68482 if(key == NULL || cc == NULL)
68483 return UA_STATUSCODE_BADINTERNALERROR;
68484
68485 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
68486 return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
68487}
68488
68489static UA_StatusCode
68490channelContext_setRemoteSymSigningKey_sp_basic256(Basic256_ChannelContext *cc,
68491 const UA_ByteString *key) {
68492 if(key == NULL || cc == NULL)
68493 return UA_STATUSCODE_BADINTERNALERROR;
68494
68495 UA_ByteString_clear(&cc->remoteSymSigningKey);
68496 return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
68497}
68498
68499static UA_StatusCode
68500channelContext_setRemoteSymIv_sp_basic256(Basic256_ChannelContext *cc,
68501 const UA_ByteString *iv) {
68502 if(iv == NULL || cc == NULL)
68503 return UA_STATUSCODE_BADINTERNALERROR;
68504
68505 UA_ByteString_clear(&cc->remoteSymIv);
68506 return UA_ByteString_copy(iv, &cc->remoteSymIv);
68507}
68508
68509static UA_StatusCode
68510channelContext_compareCertificate_sp_basic256(const Basic256_ChannelContext *cc,
68511 const UA_ByteString *certificate) {
68512 if(cc == NULL || certificate == NULL)
68513 return UA_STATUSCODE_BADINTERNALERROR;
68514
68515 mbedtls_x509_crt cert;
68516 mbedtls_x509_crt_init(&cert);
68517 int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
68518 if(mbedErr)
68519 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68520
68521 UA_StatusCode retval = UA_STATUSCODE_GOOD;
68522 if(cert.raw.len != cc->remoteCertificate.raw.len ||
68523 memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
68524 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68525
68526 mbedtls_x509_crt_free(&cert);
68527 return retval;
68528}
68529
68530static void
68531clear_sp_basic256(UA_SecurityPolicy *securityPolicy) {
68532 if(securityPolicy == NULL)
68533 return;
68534
68535 UA_ByteString_clear(&securityPolicy->localCertificate);
68536
68537 if(securityPolicy->policyContext == NULL)
68538 return;
68539
68540 /* delete all allocated members in the context */
68541 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)
68542 securityPolicy->policyContext;
68543
68544 mbedtls_ctr_drbg_free(&pc->drbgContext);
68545 mbedtls_entropy_free(&pc->entropyContext);
68546 mbedtls_pk_free(&pc->localPrivateKey);
68547 mbedtls_md_free(&pc->sha1MdContext);
68548 UA_ByteString_clear(&pc->localCertThumbprint);
68549
68550 UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68551 "Deleted members of EndpointContext for sp_basic256");
68552
68553 UA_free(pc);
68554 securityPolicy->policyContext = NULL;
68555}
68556
68557static UA_StatusCode
68558updateCertificateAndPrivateKey_sp_basic256(UA_SecurityPolicy *securityPolicy,
68559 const UA_ByteString newCertificate,
68560 const UA_ByteString newPrivateKey) {
68561 if(securityPolicy == NULL)
68562 return UA_STATUSCODE_BADINTERNALERROR;
68563
68564 if(securityPolicy->policyContext == NULL)
68565 return UA_STATUSCODE_BADINTERNALERROR;
68566
68567 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)
68568 securityPolicy->policyContext;
68569
68570 UA_ByteString_clear(&securityPolicy->localCertificate);
68571
68572 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
68573
68574 if (retval != UA_STATUSCODE_GOOD)
68575 return retval;
68576
68577 /* Set the new private key */
68578 mbedtls_pk_free(&pc->localPrivateKey);
68579 mbedtls_pk_init(&pc->localPrivateKey);
68580
68581 int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
68582
68583 if(mbedErr) {
68584 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68585 goto error;
68586 }
68587
68588 retval = asym_makeThumbprint_sp_basic256(securityPolicy,
68589 &securityPolicy->localCertificate,
68590 &pc->localCertThumbprint);
68591 if(retval != UA_STATUSCODE_GOOD)
68592 goto error;
68593
68594 return retval;
68595
68596 error:
68597 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68598 "Could not update certificate and private key");
68599 if(securityPolicy->policyContext != NULL)
68600 clear_sp_basic256(securityPolicy);
68601 return retval;
68602}
68603
68604static UA_StatusCode
68605policyContext_newContext_sp_basic256(UA_SecurityPolicy *securityPolicy,
68606 const UA_ByteString localPrivateKey) {
68607 UA_StatusCode retval = UA_STATUSCODE_GOOD;
68608 if(securityPolicy == NULL)
68609 return UA_STATUSCODE_BADINTERNALERROR;
68610
68611 if (localPrivateKey.length == 0) {
68612 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68613 "Can not initialize security policy. Private key is empty.");
68614 return UA_STATUSCODE_BADINVALIDARGUMENT;
68615 }
68616
68617 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)
68618 UA_malloc(sizeof(Basic256_PolicyContext));
68619 securityPolicy->policyContext = (void *)pc;
68620 if(!pc) {
68621 retval = UA_STATUSCODE_BADOUTOFMEMORY;
68622 goto error;
68623 }
68624
68625 /* Initialize the PolicyContext */
68626 memset(pc, 0, sizeof(Basic256_PolicyContext));
68627 mbedtls_ctr_drbg_init(&pc->drbgContext);
68628 mbedtls_entropy_init(&pc->entropyContext);
68629 mbedtls_pk_init(&pc->localPrivateKey);
68630 mbedtls_md_init(&pc->sha1MdContext);
68631
68632 /* Initialized the message digest */
68633 const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
68634 int mbedErr = mbedtls_md_setup(&pc->sha1MdContext, mdInfo, MBEDTLS_MD_SHA1);
68635 if(mbedErr) {
68636 retval = UA_STATUSCODE_BADOUTOFMEMORY;
68637 goto error;
68638 }
68639
68640 mbedErr = mbedtls_entropy_self_test(0);
68641
68642 if(mbedErr) {
68643 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68644 goto error;
68645 }
68646
68647 /* Seed the RNG */
68648 char *personalization = "open62541-drbg";
68649 mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
68650 &pc->entropyContext,
68651 (const unsigned char *)personalization, 14);
68652 if(mbedErr) {
68653 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68654 goto error;
68655 }
68656
68657 /* Set the private key */
68658 mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
68659 if(mbedErr) {
68660 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68661 goto error;
68662 }
68663
68664 /* Set the local certificate thumbprint */
68665 retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
68666 if(retval != UA_STATUSCODE_GOOD)
68667 goto error;
68668 retval = asym_makeThumbprint_sp_basic256(securityPolicy,
68669 &securityPolicy->localCertificate,
68670 &pc->localCertThumbprint);
68671 if(retval != UA_STATUSCODE_GOOD)
68672 goto error;
68673
68674 return UA_STATUSCODE_GOOD;
68675
68676error:
68677 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68678 "Could not create securityContext: %s", UA_StatusCode_name(retval));
68679 if(securityPolicy->policyContext != NULL)
68680 clear_sp_basic256(securityPolicy);
68681 return retval;
68682}
68683
68684UA_StatusCode
68685UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
68686 const UA_ByteString localPrivateKey, const UA_Logger *logger) {
68687 memset(policy, 0, sizeof(UA_SecurityPolicy));
68688 policy->logger = logger;
68689
68690 policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256\0");
68691
68692 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
68693 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
68694 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
68695
68696 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
68697
68698 if (retval != UA_STATUSCODE_GOOD)
68699 return retval;
68700
68701 /* AsymmetricModule */
68702 UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
68703 &asymmetricModule->cryptoModule.signatureAlgorithm;
68704 asym_signatureAlgorithm->uri =
68705 UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
68706 asym_signatureAlgorithm->verify =
68707 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256;
68708 asym_signatureAlgorithm->sign =
68709 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256;
68710 asym_signatureAlgorithm->getLocalSignatureSize =
68711 (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic256;
68712 asym_signatureAlgorithm->getRemoteSignatureSize =
68713 (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic256;
68714 asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
68715 asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
68716
68717 UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
68718 &asymmetricModule->cryptoModule.encryptionAlgorithm;
68719 asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
68720 asym_encryptionAlgorithm->encrypt =
68721 (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic256;
68722 asym_encryptionAlgorithm->decrypt =
68723 (UA_StatusCode(*)(void *, UA_ByteString *))asym_decrypt_sp_basic256;
68724 asym_encryptionAlgorithm->getLocalKeyLength =
68725 (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic256;
68726 asym_encryptionAlgorithm->getRemoteKeyLength =
68727 (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic256;
68728 asym_encryptionAlgorithm->getRemoteBlockSize =
68729 (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic256;
68730 asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
68731 (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic256;
68732
68733 asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256;
68734 asymmetricModule->compareCertificateThumbprint =
68735 asymmetricModule_compareCertificateThumbprint_sp_basic256;
68736
68737 /* SymmetricModule */
68738 symmetricModule->generateKey = sym_generateKey_sp_basic256;
68739 symmetricModule->generateNonce = sym_generateNonce_sp_basic256;
68740
68741 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
68742 &symmetricModule->cryptoModule.signatureAlgorithm;
68743 sym_signatureAlgorithm->uri =
68744 UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
68745 sym_signatureAlgorithm->verify =
68746 (UA_StatusCode (*)(void *, const UA_ByteString *,
68747 const UA_ByteString *))sym_verify_sp_basic256;
68748 sym_signatureAlgorithm->sign =
68749 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256;
68750 sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic256;
68751 sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic256;
68752 sym_signatureAlgorithm->getLocalKeyLength =
68753 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256;
68754 sym_signatureAlgorithm->getRemoteKeyLength =
68755 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256;
68756
68757 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
68758 &symmetricModule->cryptoModule.encryptionAlgorithm;
68759 sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
68760 sym_encryptionAlgorithm->encrypt =
68761 (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic256;
68762 sym_encryptionAlgorithm->decrypt =
68763 (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic256;
68764 sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic256;
68765 sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic256;
68766 sym_encryptionAlgorithm->getRemoteBlockSize =
68767 (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic256;
68768 sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
68769 (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic256;
68770 symmetricModule->secureChannelNonceLength = 32;
68771
68772 // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
68773 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
68774
68775 /* ChannelModule */
68776 channelModule->newContext = channelContext_newContext_sp_basic256;
68777 channelModule->deleteContext = (void (*)(void *))
68778 channelContext_deleteContext_sp_basic256;
68779
68780 channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68781 channelContext_setLocalSymEncryptingKey_sp_basic256;
68782 channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68783 channelContext_setLocalSymSigningKey_sp_basic256;
68784 channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
68785 channelContext_setLocalSymIv_sp_basic256;
68786
68787 channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68788 channelContext_setRemoteSymEncryptingKey_sp_basic256;
68789 channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68790 channelContext_setRemoteSymSigningKey_sp_basic256;
68791 channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
68792 channelContext_setRemoteSymIv_sp_basic256;
68793
68794 channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
68795 channelContext_compareCertificate_sp_basic256;
68796
68797 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256;
68798 policy->clear = clear_sp_basic256;
68799
68800 UA_StatusCode res = policyContext_newContext_sp_basic256(policy, localPrivateKey);
68801 if(res != UA_STATUSCODE_GOOD)
68802 clear_sp_basic256(policy);
68803
68804 return res;
68805}
68806
68807#endif
68808
68809/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic256sha256.c" ****/
68810
68811/* This Source Code Form is subject to the terms of the Mozilla Public
68812 * License, v. 2.0. If a copy of the MPL was not distributed with this
68813 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
68814 *
68815 * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
68816 * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
68817 * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green)
68818 * Copyright 2020 (c) Wind River Systems, Inc.
68819 * Copyright 2020 (c) basysKom GmbH
68820 */
68821
68822
68823#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
68824
68825
68826#include <mbedtls/aes.h>
68827#include <mbedtls/ctr_drbg.h>
68828#include <mbedtls/entropy.h>
68829#include <mbedtls/error.h>
68830#include <mbedtls/md.h>
68831#include <mbedtls/sha1.h>
68832#include <mbedtls/sha256.h>
68833#include <mbedtls/version.h>
68834#include <mbedtls/x509_crt.h>
68835
68836/* Notes:
68837 * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to
68838 * allocate temp buffers.
68839 * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
68840 */
68841
68842#define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42
68843#define UA_SHA1_LENGTH 20
68844#define UA_SHA256_LENGTH 32
68845#define UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32
68846#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_KEY_LENGTH 32
68847#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE 16
68848#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
68849#define UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH 256
68850#define UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH 512
68851
68852typedef struct {
68853 UA_ByteString localCertThumbprint;
68854
68855 mbedtls_ctr_drbg_context drbgContext;
68856 mbedtls_entropy_context entropyContext;
68857 mbedtls_md_context_t sha256MdContext;
68858 mbedtls_pk_context localPrivateKey;
68859} Basic256Sha256_PolicyContext;
68860
68861typedef struct {
68862 Basic256Sha256_PolicyContext *policyContext;
68863
68864 UA_ByteString localSymSigningKey;
68865 UA_ByteString localSymEncryptingKey;
68866 UA_ByteString localSymIv;
68867
68868 UA_ByteString remoteSymSigningKey;
68869 UA_ByteString remoteSymEncryptingKey;
68870 UA_ByteString remoteSymIv;
68871
68872 mbedtls_x509_crt remoteCertificate;
68873} Basic256Sha256_ChannelContext;
68874
68875/********************/
68876/* AsymmetricModule */
68877/********************/
68878
68879/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
68880static UA_StatusCode
68881asym_verify_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
68882 const UA_ByteString *message,
68883 const UA_ByteString *signature) {
68884 if(message == NULL || signature == NULL || cc == NULL)
68885 return UA_STATUSCODE_BADINTERNALERROR;
68886
68887 unsigned char hash[UA_SHA256_LENGTH];
68888#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68889 // TODO check return status
68890 mbedtls_sha256_ret(message->data, message->length, hash, 0);
68891#else
68892 mbedtls_sha256(message->data, message->length, hash, 0);
68893#endif
68894
68895 /* Set the RSA settings */
68896 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68897 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
68898
68899 /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_verify() */
68900 /* Alternatively, use more specific function mbedtls_rsa_rsassa_pkcs1_v15_verify(), i.e. */
68901 /* int mbedErr = mbedtls_rsa_rsassa_pkcs1_v15_verify(rsaContext, NULL, NULL,
68902 MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,
68903 UA_SHA256_LENGTH, hash,
68904 signature->data); */
68905 int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk,
68906 MBEDTLS_MD_SHA256, hash, UA_SHA256_LENGTH,
68907 signature->data, signature->length);
68908
68909 if(mbedErr)
68910 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68911 return UA_STATUSCODE_GOOD;
68912}
68913
68914/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
68915static UA_StatusCode
68916asym_sign_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
68917 const UA_ByteString *message,
68918 UA_ByteString *signature) {
68919 if(message == NULL || signature == NULL || cc == NULL)
68920 return UA_STATUSCODE_BADINTERNALERROR;
68921
68922 unsigned char hash[UA_SHA256_LENGTH];
68923#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68924 // TODO check return status
68925 mbedtls_sha256_ret(message->data, message->length, hash, 0);
68926#else
68927 mbedtls_sha256(message->data, message->length, hash, 0);
68928#endif
68929
68930 Basic256Sha256_PolicyContext *pc = cc->policyContext;
68931 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey);
68932 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
68933
68934 size_t sigLen = 0;
68935
68936 /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_sign */
68937 /* Alternatively use more specific function mbedtls_rsa_rsassa_pkcs1_v15_sign() */
68938 int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey,
68939 MBEDTLS_MD_SHA256, hash,
68940 UA_SHA256_LENGTH, signature->data,
68941#if MBEDTLS_VERSION_NUMBER >= 0x03000000
68942 signature->length,
68943#endif
68944 &sigLen, mbedtls_ctr_drbg_random,
68945 &pc->drbgContext);
68946 if(mbedErr)
68947 return UA_STATUSCODE_BADINTERNALERROR;
68948 return UA_STATUSCODE_GOOD;
68949}
68950
68951static size_t
68952asym_getLocalSignatureSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
68953 if(cc == NULL)
68954 return 0;
68955#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68956 return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
68957#else
68958 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
68959#endif
68960}
68961
68962static size_t
68963asym_getRemoteSignatureSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
68964 if(cc == NULL)
68965 return 0;
68966#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68967 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
68968#else
68969 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
68970#endif
68971}
68972
68973static size_t
68974asym_getRemoteBlockSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
68975#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68976 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68977 return rsaContext->len;
68978#else
68979 if(cc == NULL)
68980 return 0;
68981 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
68982#endif
68983}
68984
68985static size_t
68986asym_getRemotePlainTextBlockSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
68987#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68988 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68989 return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
68990#else
68991 if(cc == NULL)
68992 return 0;
68993 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
68994 UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
68995#endif
68996}
68997
68998
68999/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
69000static UA_StatusCode
69001asym_encrypt_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69002 UA_ByteString *data) {
69003 if(cc == NULL || data == NULL)
69004 return UA_STATUSCODE_BADINTERNALERROR;
69005
69006 const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_basic256sha256(cc);
69007
69008 mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69009 mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
69010
69011 return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext,
69012 data, plainTextBlockSize);
69013}
69014
69015/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
69016static UA_StatusCode
69017asym_decrypt_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69018 UA_ByteString *data) {
69019 if(cc == NULL || data == NULL)
69020 return UA_STATUSCODE_BADINTERNALERROR;
69021 return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
69022 &cc->policyContext->drbgContext, data);
69023}
69024
69025static size_t
69026asym_getLocalEncryptionKeyLength_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
69027 return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
69028}
69029
69030static size_t
69031asym_getRemoteEncryptionKeyLength_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
69032 return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
69033}
69034
69035static UA_StatusCode
69036asym_makeThumbprint_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
69037 const UA_ByteString *certificate,
69038 UA_ByteString *thumbprint) {
69039 if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
69040 return UA_STATUSCODE_BADINTERNALERROR;
69041 return mbedtls_thumbprint_sha1(certificate, thumbprint);
69042}
69043
69044static UA_StatusCode
69045asymmetricModule_compareCertificateThumbprint_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
69046 const UA_ByteString *certificateThumbprint) {
69047 if(securityPolicy == NULL || certificateThumbprint == NULL)
69048 return UA_STATUSCODE_BADINTERNALERROR;
69049
69050 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
69051 if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
69052 return UA_STATUSCODE_BADCERTIFICATEINVALID;
69053
69054 return UA_STATUSCODE_GOOD;
69055}
69056
69057/*******************/
69058/* SymmetricModule */
69059/*******************/
69060
69061static UA_StatusCode
69062sym_verify_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69063 const UA_ByteString *message,
69064 const UA_ByteString *signature) {
69065 if(cc == NULL || message == NULL || signature == NULL)
69066 return UA_STATUSCODE_BADINTERNALERROR;
69067
69068 /* Compute MAC */
69069 if(signature->length != UA_SHA256_LENGTH)
69070 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69071
69072 Basic256Sha256_PolicyContext *pc = cc->policyContext;
69073 unsigned char mac[UA_SHA256_LENGTH];
69074 mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac);
69075
69076 /* Compare with Signature */
69077 if(!UA_constantTimeEqual(signature->data, mac, UA_SHA256_LENGTH))
69078 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69079 return UA_STATUSCODE_GOOD;
69080}
69081
69082static UA_StatusCode
69083sym_sign_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
69084 const UA_ByteString *message,
69085 UA_ByteString *signature) {
69086 if(signature->length != UA_SHA256_LENGTH)
69087 return UA_STATUSCODE_BADINTERNALERROR;
69088
69089 mbedtls_hmac(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey,
69090 message, signature->data);
69091 return UA_STATUSCODE_GOOD;
69092}
69093
69094static size_t
69095sym_getSignatureSize_sp_basic256sha256(const void *channelContext) {
69096 return UA_SHA256_LENGTH;
69097}
69098
69099static size_t
69100sym_getSigningKeyLength_sp_basic256sha256(const void *channelContext) {
69101 return UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
69102}
69103
69104static size_t
69105sym_getEncryptionKeyLength_sp_basic256sha256(const void *channelContext) {
69106 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_KEY_LENGTH;
69107}
69108
69109static size_t
69110sym_getEncryptionBlockSize_sp_basic256sha256(const void *channelContext) {
69111 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
69112}
69113
69114static size_t
69115sym_getPlainTextBlockSize_sp_basic256sha256(const void *channelContext) {
69116 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE;
69117}
69118
69119static UA_StatusCode
69120sym_encrypt_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
69121 UA_ByteString *data) {
69122 if(cc == NULL || data == NULL)
69123 return UA_STATUSCODE_BADINTERNALERROR;
69124
69125 if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE)
69126 return UA_STATUSCODE_BADINTERNALERROR;
69127
69128 size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE;
69129
69130 if(data->length % plainTextBlockSize != 0)
69131 return UA_STATUSCODE_BADINTERNALERROR;
69132
69133 /* Keylength in bits */
69134 unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
69135 mbedtls_aes_context aesContext;
69136 int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
69137 if(mbedErr)
69138 return UA_STATUSCODE_BADINTERNALERROR;
69139
69140 UA_ByteString ivCopy;
69141 UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
69142 if(retval != UA_STATUSCODE_GOOD)
69143 return retval;
69144
69145 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
69146 ivCopy.data, data->data, data->data);
69147 if(mbedErr)
69148 retval = UA_STATUSCODE_BADINTERNALERROR;
69149 UA_ByteString_clear(&ivCopy);
69150 return retval;
69151}
69152
69153static UA_StatusCode
69154sym_decrypt_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
69155 UA_ByteString *data) {
69156 if(cc == NULL || data == NULL)
69157 return UA_STATUSCODE_BADINTERNALERROR;
69158
69159 size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
69160 if(cc->remoteSymIv.length != encryptionBlockSize)
69161 return UA_STATUSCODE_BADINTERNALERROR;
69162
69163 if(data->length % encryptionBlockSize != 0)
69164 return UA_STATUSCODE_BADINTERNALERROR;
69165
69166 unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
69167 mbedtls_aes_context aesContext;
69168 int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength);
69169 if(mbedErr)
69170 return UA_STATUSCODE_BADINTERNALERROR;
69171
69172 UA_ByteString ivCopy;
69173 UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
69174 if(retval != UA_STATUSCODE_GOOD)
69175 return retval;
69176
69177 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
69178 ivCopy.data, data->data, data->data);
69179 if(mbedErr)
69180 retval = UA_STATUSCODE_BADINTERNALERROR;
69181 UA_ByteString_clear(&ivCopy);
69182 return retval;
69183}
69184
69185static UA_StatusCode
69186sym_generateKey_sp_basic256sha256(void *policyContext, const UA_ByteString *secret,
69187 const UA_ByteString *seed, UA_ByteString *out) {
69188 if(secret == NULL || seed == NULL || out == NULL)
69189 return UA_STATUSCODE_BADINTERNALERROR;
69190 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)policyContext;
69191 return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out);
69192}
69193
69194static UA_StatusCode
69195sym_generateNonce_sp_basic256sha256(void *policyContext, UA_ByteString *out) {
69196 if(out == NULL)
69197 return UA_STATUSCODE_BADINTERNALERROR;
69198 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)policyContext;
69199 int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
69200 if(mbedErr)
69201 return UA_STATUSCODE_BADUNEXPECTEDERROR;
69202 return UA_STATUSCODE_GOOD;
69203}
69204
69205/*****************/
69206/* ChannelModule */
69207/*****************/
69208
69209/* Assumes that the certificate has been verified externally */
69210static UA_StatusCode
69211parseRemoteCertificate_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69212 const UA_ByteString *remoteCertificate) {
69213 if(remoteCertificate == NULL || cc == NULL)
69214 return UA_STATUSCODE_BADINTERNALERROR;
69215
69216 /* Parse the certificate */
69217 int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
69218 remoteCertificate->length);
69219 if(mbedErr)
69220 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69221
69222 /* Check the key length */
69223#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69224 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69225 if(rsaContext->len < UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH ||
69226 rsaContext->len > UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH)
69227#else
69228 size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
69229 if(keylen < UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH ||
69230 keylen > UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH)
69231#endif
69232 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
69233
69234 return UA_STATUSCODE_GOOD;
69235}
69236
69237static void
69238channelContext_deleteContext_sp_basic256sha256(Basic256Sha256_ChannelContext *cc) {
69239 UA_ByteString_clear(&cc->localSymSigningKey);
69240 UA_ByteString_clear(&cc->localSymEncryptingKey);
69241 UA_ByteString_clear(&cc->localSymIv);
69242
69243 UA_ByteString_clear(&cc->remoteSymSigningKey);
69244 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
69245 UA_ByteString_clear(&cc->remoteSymIv);
69246
69247 mbedtls_x509_crt_free(&cc->remoteCertificate);
69248
69249 UA_free(cc);
69250}
69251
69252static UA_StatusCode
69253channelContext_newContext_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
69254 const UA_ByteString *remoteCertificate,
69255 void **pp_contextData) {
69256 if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
69257 return UA_STATUSCODE_BADINTERNALERROR;
69258
69259 /* Allocate the channel context */
69260 *pp_contextData = UA_malloc(sizeof(Basic256Sha256_ChannelContext));
69261 if(*pp_contextData == NULL)
69262 return UA_STATUSCODE_BADOUTOFMEMORY;
69263
69264 Basic256Sha256_ChannelContext *cc = (Basic256Sha256_ChannelContext *)*pp_contextData;
69265
69266 /* Initialize the channel context */
69267 cc->policyContext = (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
69268
69269 UA_ByteString_init(&cc->localSymSigningKey);
69270 UA_ByteString_init(&cc->localSymEncryptingKey);
69271 UA_ByteString_init(&cc->localSymIv);
69272
69273 UA_ByteString_init(&cc->remoteSymSigningKey);
69274 UA_ByteString_init(&cc->remoteSymEncryptingKey);
69275 UA_ByteString_init(&cc->remoteSymIv);
69276
69277 mbedtls_x509_crt_init(&cc->remoteCertificate);
69278
69279 // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
69280 UA_StatusCode retval = parseRemoteCertificate_sp_basic256sha256(cc, remoteCertificate);
69281 if(retval != UA_STATUSCODE_GOOD) {
69282 channelContext_deleteContext_sp_basic256sha256(cc);
69283 *pp_contextData = NULL;
69284 }
69285 return retval;
69286}
69287
69288static UA_StatusCode
69289channelContext_setLocalSymEncryptingKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69290 const UA_ByteString *key) {
69291 if(key == NULL || cc == NULL)
69292 return UA_STATUSCODE_BADINTERNALERROR;
69293
69294 UA_ByteString_clear(&cc->localSymEncryptingKey);
69295 return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
69296}
69297
69298static UA_StatusCode
69299channelContext_setLocalSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69300 const UA_ByteString *key) {
69301 if(key == NULL || cc == NULL)
69302 return UA_STATUSCODE_BADINTERNALERROR;
69303
69304 UA_ByteString_clear(&cc->localSymSigningKey);
69305 return UA_ByteString_copy(key, &cc->localSymSigningKey);
69306}
69307
69308
69309static UA_StatusCode
69310channelContext_setLocalSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69311 const UA_ByteString *iv) {
69312 if(iv == NULL || cc == NULL)
69313 return UA_STATUSCODE_BADINTERNALERROR;
69314
69315 UA_ByteString_clear(&cc->localSymIv);
69316 return UA_ByteString_copy(iv, &cc->localSymIv);
69317}
69318
69319static UA_StatusCode
69320channelContext_setRemoteSymEncryptingKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69321 const UA_ByteString *key) {
69322 if(key == NULL || cc == NULL)
69323 return UA_STATUSCODE_BADINTERNALERROR;
69324
69325 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
69326 return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
69327}
69328
69329static UA_StatusCode
69330channelContext_setRemoteSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69331 const UA_ByteString *key) {
69332 if(key == NULL || cc == NULL)
69333 return UA_STATUSCODE_BADINTERNALERROR;
69334
69335 UA_ByteString_clear(&cc->remoteSymSigningKey);
69336 return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
69337}
69338
69339static UA_StatusCode
69340channelContext_setRemoteSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69341 const UA_ByteString *iv) {
69342 if(iv == NULL || cc == NULL)
69343 return UA_STATUSCODE_BADINTERNALERROR;
69344
69345 UA_ByteString_clear(&cc->remoteSymIv);
69346 return UA_ByteString_copy(iv, &cc->remoteSymIv);
69347}
69348
69349static UA_StatusCode
69350channelContext_compareCertificate_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
69351 const UA_ByteString *certificate) {
69352 if(cc == NULL || certificate == NULL)
69353 return UA_STATUSCODE_BADINTERNALERROR;
69354
69355 mbedtls_x509_crt cert;
69356 mbedtls_x509_crt_init(&cert);
69357 int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
69358 if(mbedErr)
69359 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69360
69361 UA_StatusCode retval = UA_STATUSCODE_GOOD;
69362 if(cert.raw.len != cc->remoteCertificate.raw.len ||
69363 memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
69364 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69365
69366 mbedtls_x509_crt_free(&cert);
69367 return retval;
69368}
69369
69370static void
69371clear_sp_basic256sha256(UA_SecurityPolicy *securityPolicy) {
69372 if(securityPolicy == NULL)
69373 return;
69374
69375 UA_ByteString_clear(&securityPolicy->localCertificate);
69376
69377 if(securityPolicy->policyContext == NULL)
69378 return;
69379
69380 /* delete all allocated members in the context */
69381 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)
69382 securityPolicy->policyContext;
69383
69384 mbedtls_ctr_drbg_free(&pc->drbgContext);
69385 mbedtls_entropy_free(&pc->entropyContext);
69386 mbedtls_pk_free(&pc->localPrivateKey);
69387 mbedtls_md_free(&pc->sha256MdContext);
69388 UA_ByteString_clear(&pc->localCertThumbprint);
69389
69390 UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
69391 "Deleted members of EndpointContext for sp_basic256sha256");
69392
69393 UA_free(pc);
69394 securityPolicy->policyContext = NULL;
69395}
69396
69397static UA_StatusCode
69398updateCertificateAndPrivateKey_sp_basic256sha256(UA_SecurityPolicy *securityPolicy,
69399 const UA_ByteString newCertificate,
69400 const UA_ByteString newPrivateKey) {
69401 if(securityPolicy == NULL)
69402 return UA_STATUSCODE_BADINTERNALERROR;
69403
69404 if(securityPolicy->policyContext == NULL)
69405 return UA_STATUSCODE_BADINTERNALERROR;
69406
69407 Basic256Sha256_PolicyContext *pc =
69408 (Basic256Sha256_PolicyContext *) securityPolicy->policyContext;
69409
69410 UA_ByteString_clear(&securityPolicy->localCertificate);
69411
69412 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
69413
69414 if (retval != UA_STATUSCODE_GOOD)
69415 return retval;
69416
69417 /* Set the new private key */
69418 mbedtls_pk_free(&pc->localPrivateKey);
69419 mbedtls_pk_init(&pc->localPrivateKey);
69420 int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
69421 if(mbedErr) {
69422 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69423 goto error;
69424 }
69425
69426 retval = asym_makeThumbprint_sp_basic256sha256(securityPolicy,
69427 &securityPolicy->localCertificate,
69428 &pc->localCertThumbprint);
69429 if(retval != UA_STATUSCODE_GOOD)
69430 goto error;
69431
69432 return retval;
69433
69434 error:
69435 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
69436 "Could not update certificate and private key");
69437 if(securityPolicy->policyContext != NULL)
69438 clear_sp_basic256sha256(securityPolicy);
69439 return retval;
69440}
69441
69442static UA_StatusCode
69443policyContext_newContext_sp_basic256sha256(UA_SecurityPolicy *securityPolicy,
69444 const UA_ByteString localPrivateKey) {
69445 UA_StatusCode retval = UA_STATUSCODE_GOOD;
69446 if(securityPolicy == NULL)
69447 return UA_STATUSCODE_BADINTERNALERROR;
69448
69449 if (localPrivateKey.length == 0) {
69450 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
69451 "Can not initialize security policy. Private key is empty.");
69452 return UA_STATUSCODE_BADINVALIDARGUMENT;
69453 }
69454
69455 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)
69456 UA_malloc(sizeof(Basic256Sha256_PolicyContext));
69457 securityPolicy->policyContext = (void *)pc;
69458 if(!pc) {
69459 retval = UA_STATUSCODE_BADOUTOFMEMORY;
69460 goto error;
69461 }
69462
69463 /* Initialize the PolicyContext */
69464 memset(pc, 0, sizeof(Basic256Sha256_PolicyContext));
69465 mbedtls_ctr_drbg_init(&pc->drbgContext);
69466 mbedtls_entropy_init(&pc->entropyContext);
69467 mbedtls_pk_init(&pc->localPrivateKey);
69468 mbedtls_md_init(&pc->sha256MdContext);
69469
69470 /* Initialized the message digest */
69471 const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
69472 int mbedErr = mbedtls_md_setup(&pc->sha256MdContext, mdInfo, MBEDTLS_MD_SHA256);
69473 if(mbedErr) {
69474 retval = UA_STATUSCODE_BADOUTOFMEMORY;
69475 goto error;
69476 }
69477
69478 mbedErr = mbedtls_entropy_self_test(0);
69479
69480 if(mbedErr) {
69481 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69482 goto error;
69483 }
69484
69485 /* Seed the RNG */
69486 char *personalization = "open62541-drbg";
69487 mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
69488 &pc->entropyContext,
69489 (const unsigned char *)personalization, 14);
69490 if(mbedErr) {
69491 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69492 goto error;
69493 }
69494
69495 /* Set the private key */
69496 mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
69497 if(mbedErr) {
69498 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69499 goto error;
69500 }
69501
69502 /* Set the local certificate thumbprint */
69503 retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
69504 if(retval != UA_STATUSCODE_GOOD)
69505 goto error;
69506 retval = asym_makeThumbprint_sp_basic256sha256(securityPolicy,
69507 &securityPolicy->localCertificate,
69508 &pc->localCertThumbprint);
69509 if(retval != UA_STATUSCODE_GOOD)
69510 goto error;
69511
69512 return UA_STATUSCODE_GOOD;
69513
69514error:
69515 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
69516 "Could not create securityContext: %s", UA_StatusCode_name(retval));
69517 if(securityPolicy->policyContext != NULL)
69518 clear_sp_basic256sha256(securityPolicy);
69519 return retval;
69520}
69521
69522UA_StatusCode
69523UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
69524 const UA_ByteString localPrivateKey, const UA_Logger *logger) {
69525 memset(policy, 0, sizeof(UA_SecurityPolicy));
69526 policy->logger = logger;
69527
69528 policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256");
69529
69530 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
69531 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
69532 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
69533
69534 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
69535
69536 if (retval != UA_STATUSCODE_GOOD)
69537 return retval;
69538
69539 /* AsymmetricModule */
69540 UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
69541 &asymmetricModule->cryptoModule.signatureAlgorithm;
69542 asym_signatureAlgorithm->uri =
69543 UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
69544 asym_signatureAlgorithm->verify =
69545 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256sha256;
69546 asym_signatureAlgorithm->sign =
69547 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256sha256;
69548 asym_signatureAlgorithm->getLocalSignatureSize =
69549 (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic256sha256;
69550 asym_signatureAlgorithm->getRemoteSignatureSize =
69551 (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic256sha256;
69552 asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
69553 asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
69554
69555 UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
69556 &asymmetricModule->cryptoModule.encryptionAlgorithm;
69557 asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
69558 asym_encryptionAlgorithm->encrypt =
69559 (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic256sha256;
69560 asym_encryptionAlgorithm->decrypt =
69561 (UA_StatusCode(*)(void *, UA_ByteString *))
69562 asym_decrypt_sp_basic256sha256;
69563 asym_encryptionAlgorithm->getLocalKeyLength =
69564 (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic256sha256;
69565 asym_encryptionAlgorithm->getRemoteKeyLength =
69566 (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic256sha256;
69567 asym_encryptionAlgorithm->getRemoteBlockSize =
69568 (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic256sha256;
69569 asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
69570 (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic256sha256;
69571
69572 asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256sha256;
69573 asymmetricModule->compareCertificateThumbprint =
69574 asymmetricModule_compareCertificateThumbprint_sp_basic256sha256;
69575
69576 /* SymmetricModule */
69577 symmetricModule->generateKey = sym_generateKey_sp_basic256sha256;
69578 symmetricModule->generateNonce = sym_generateNonce_sp_basic256sha256;
69579
69580 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
69581 &symmetricModule->cryptoModule.signatureAlgorithm;
69582 sym_signatureAlgorithm->uri =
69583 UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
69584 sym_signatureAlgorithm->verify =
69585 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_basic256sha256;
69586 sym_signatureAlgorithm->sign =
69587 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256sha256;
69588 sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic256sha256;
69589 sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic256sha256;
69590 sym_signatureAlgorithm->getLocalKeyLength =
69591 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256sha256;
69592 sym_signatureAlgorithm->getRemoteKeyLength =
69593 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256sha256;
69594
69595 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
69596 &symmetricModule->cryptoModule.encryptionAlgorithm;
69597 sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc");
69598 sym_encryptionAlgorithm->encrypt =
69599 (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic256sha256;
69600 sym_encryptionAlgorithm->decrypt =
69601 (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic256sha256;
69602 sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic256sha256;
69603 sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic256sha256;
69604 sym_encryptionAlgorithm->getRemoteBlockSize =
69605 (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic256sha256;
69606 sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
69607 (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic256sha256;
69608 symmetricModule->secureChannelNonceLength = 32;
69609
69610 // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
69611 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
69612
69613 /* ChannelModule */
69614 channelModule->newContext = channelContext_newContext_sp_basic256sha256;
69615 channelModule->deleteContext = (void (*)(void *))
69616 channelContext_deleteContext_sp_basic256sha256;
69617
69618 channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
69619 channelContext_setLocalSymEncryptingKey_sp_basic256sha256;
69620 channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
69621 channelContext_setLocalSymSigningKey_sp_basic256sha256;
69622 channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
69623 channelContext_setLocalSymIv_sp_basic256sha256;
69624
69625 channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
69626 channelContext_setRemoteSymEncryptingKey_sp_basic256sha256;
69627 channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
69628 channelContext_setRemoteSymSigningKey_sp_basic256sha256;
69629 channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
69630 channelContext_setRemoteSymIv_sp_basic256sha256;
69631
69632 channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
69633 channelContext_compareCertificate_sp_basic256sha256;
69634
69635 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256sha256;
69636 policy->clear = clear_sp_basic256sha256;
69637
69638 UA_StatusCode res = policyContext_newContext_sp_basic256sha256(policy, localPrivateKey);
69639 if(res != UA_STATUSCODE_GOOD)
69640 clear_sp_basic256sha256(policy);
69641
69642 return res;
69643}
69644
69645#endif
69646
69647/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_aes128sha256rsaoaep.c" ****/
69648
69649/* This Source Code Form is subject to the terms of the Mozilla Public
69650 * License, v. 2.0. If a copy of the MPL was not distributed with this
69651 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
69652 *
69653 * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
69654 * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
69655 * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green)
69656 * Copyright 2020 (c) Wind River Systems, Inc.
69657 */
69658
69659
69660#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
69661
69662
69663#include <mbedtls/aes.h>
69664#include <mbedtls/ctr_drbg.h>
69665#include <mbedtls/entropy.h>
69666#include <mbedtls/error.h>
69667#include <mbedtls/md.h>
69668#include <mbedtls/sha1.h>
69669#include <mbedtls/sha256.h>
69670#include <mbedtls/version.h>
69671#include <mbedtls/x509_crt.h>
69672
69673/* Notes:
69674 * mbedTLS' AES allows in-place encryption and decryption. So we don't have to
69675 * allocate temp buffers.
69676 * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
69677 */
69678
69679#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN 42
69680#define UA_SHA1_LENGTH 20
69681#define UA_SHA256_LENGTH 32
69682#define UA_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH 32
69683#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_KEY_LENGTH 16
69684#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE 16
69685#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE 16
69686#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH 256
69687#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH 512
69688
69689typedef struct {
69690 UA_ByteString localCertThumbprint;
69691
69692 mbedtls_ctr_drbg_context drbgContext;
69693 mbedtls_entropy_context entropyContext;
69694 mbedtls_md_context_t sha256MdContext;
69695 mbedtls_pk_context localPrivateKey;
69696} Aes128Sha256PsaOaep_PolicyContext;
69697
69698typedef struct {
69699 Aes128Sha256PsaOaep_PolicyContext *policyContext;
69700
69701 UA_ByteString localSymSigningKey;
69702 UA_ByteString localSymEncryptingKey;
69703 UA_ByteString localSymIv;
69704
69705 UA_ByteString remoteSymSigningKey;
69706 UA_ByteString remoteSymEncryptingKey;
69707 UA_ByteString remoteSymIv;
69708
69709 mbedtls_x509_crt remoteCertificate;
69710} Aes128Sha256PsaOaep_ChannelContext;
69711
69712/********************/
69713/* AsymmetricModule */
69714/********************/
69715
69716/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
69717static UA_StatusCode
69718asym_verify_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
69719 const UA_ByteString *message,
69720 const UA_ByteString *signature) {
69721 if(message == NULL || signature == NULL || cc == NULL)
69722 return UA_STATUSCODE_BADINTERNALERROR;
69723
69724 unsigned char hash[UA_SHA256_LENGTH];
69725#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69726 // TODO check return status
69727 mbedtls_sha256_ret(message->data, message->length, hash, 0);
69728#else
69729 mbedtls_sha256(message->data, message->length, hash, 0);
69730#endif
69731
69732 /* Set the RSA settings */
69733 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69734 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
69735
69736 /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_verify() */
69737 /* Alternatively, use more specific function mbedtls_rsa_rsassa_pkcs1_v15_verify(), i.e. */
69738 /* int mbedErr = mbedtls_rsa_rsassa_pkcs1_v15_verify(rsaContext, NULL, NULL,
69739 MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,
69740 UA_SHA256_LENGTH, hash,
69741 signature->data); */
69742 int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk,
69743 MBEDTLS_MD_SHA256, hash, UA_SHA256_LENGTH,
69744 signature->data, signature->length);
69745
69746 if(mbedErr)
69747 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69748 return UA_STATUSCODE_GOOD;
69749}
69750
69751/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
69752static UA_StatusCode
69753asym_sign_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
69754 const UA_ByteString *message,
69755 UA_ByteString *signature) {
69756 if(message == NULL || signature == NULL || cc == NULL)
69757 return UA_STATUSCODE_BADINTERNALERROR;
69758
69759 unsigned char hash[UA_SHA256_LENGTH];
69760#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69761 // TODO check return status
69762 mbedtls_sha256_ret(message->data, message->length, hash, 0);
69763#else
69764 mbedtls_sha256(message->data, message->length, hash, 0);
69765#endif
69766
69767 Aes128Sha256PsaOaep_PolicyContext *pc = cc->policyContext;
69768 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey);
69769 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
69770
69771 size_t sigLen = 0;
69772
69773 /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_sign */
69774 /* Alternatively use more specific function mbedtls_rsa_rsassa_pkcs1_v15_sign() */
69775 int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey,
69776 MBEDTLS_MD_SHA256, hash,
69777 UA_SHA256_LENGTH, signature->data,
69778#if MBEDTLS_VERSION_NUMBER >= 0x03000000
69779 signature->length,
69780#endif
69781 &sigLen, mbedtls_ctr_drbg_random,
69782 &pc->drbgContext);
69783 if(mbedErr)
69784 return UA_STATUSCODE_BADINTERNALERROR;
69785 return UA_STATUSCODE_GOOD;
69786}
69787
69788static size_t
69789asym_getLocalSignatureSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69790#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69791 return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
69792#else
69793 if(cc == NULL)
69794 return 0;
69795 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
69796#endif
69797
69798}
69799
69800static size_t
69801asym_getRemoteSignatureSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69802#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69803 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
69804#else
69805 if(cc == NULL)
69806 return 0;
69807 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
69808#endif
69809}
69810
69811static size_t
69812asym_getRemoteBlockSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69813#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69814 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
69815#else
69816 if(cc == NULL)
69817 return 0;
69818 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
69819#endif
69820}
69821
69822static size_t
69823asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69824#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69825 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69826 return rsaContext->len - UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
69827#else
69828 if(cc == NULL)
69829 return 0;
69830 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
69831 UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
69832#endif
69833}
69834
69835
69836/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
69837static UA_StatusCode
69838asym_encrypt_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
69839 UA_ByteString *data) {
69840 if(cc == NULL || data == NULL)
69841 return UA_STATUSCODE_BADINTERNALERROR;
69842
69843 const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep(cc);
69844
69845 mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69846 mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
69847
69848 return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext,
69849 data, plainTextBlockSize);
69850}
69851
69852/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
69853static UA_StatusCode
69854asym_decrypt_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
69855 UA_ByteString *data) {
69856 if(cc == NULL || data == NULL)
69857 return UA_STATUSCODE_BADINTERNALERROR;
69858 return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
69859 &cc->policyContext->drbgContext, data);
69860}
69861
69862static size_t
69863asym_getLocalEncryptionKeyLength_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69864 return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
69865}
69866
69867static size_t
69868asym_getRemoteEncryptionKeyLength_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69869 return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
69870}
69871
69872static UA_StatusCode
69873asym_makeThumbprint_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
69874 const UA_ByteString *certificate,
69875 UA_ByteString *thumbprint) {
69876 if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
69877 return UA_STATUSCODE_BADINTERNALERROR;
69878 return mbedtls_thumbprint_sha1(certificate, thumbprint);
69879}
69880
69881static UA_StatusCode
69882asymmetricModule_compareCertificateThumbprint_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
69883 const UA_ByteString *certificateThumbprint) {
69884 if(securityPolicy == NULL || certificateThumbprint == NULL)
69885 return UA_STATUSCODE_BADINTERNALERROR;
69886
69887 Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)securityPolicy->policyContext;
69888 if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
69889 return UA_STATUSCODE_BADCERTIFICATEINVALID;
69890
69891 return UA_STATUSCODE_GOOD;
69892}
69893
69894/*******************/
69895/* SymmetricModule */
69896/*******************/
69897
69898static UA_StatusCode
69899sym_verify_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
69900 const UA_ByteString *message,
69901 const UA_ByteString *signature) {
69902 if(cc == NULL || message == NULL || signature == NULL)
69903 return UA_STATUSCODE_BADINTERNALERROR;
69904
69905 /* Compute MAC */
69906 if(signature->length != UA_SHA256_LENGTH)
69907 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69908 Aes128Sha256PsaOaep_PolicyContext *pc = cc->policyContext;
69909 unsigned char mac[UA_SHA256_LENGTH];
69910 mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac);
69911
69912 /* Compare with Signature */
69913 if(!UA_constantTimeEqual(signature->data, mac, UA_SHA256_LENGTH))
69914 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69915 return UA_STATUSCODE_GOOD;
69916}
69917
69918static UA_StatusCode
69919sym_sign_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
69920 const UA_ByteString *message,
69921 UA_ByteString *signature) {
69922 if(signature->length != UA_SHA256_LENGTH)
69923 return UA_STATUSCODE_BADINTERNALERROR;
69924
69925 mbedtls_hmac(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey,
69926 message, signature->data);
69927 return UA_STATUSCODE_GOOD;
69928}
69929
69930static size_t
69931sym_getSignatureSize_sp_aes128sha256rsaoaep(const void *channelContext) {
69932 return UA_SHA256_LENGTH;
69933}
69934
69935static size_t
69936sym_getSigningKeyLength_sp_aes128sha256rsaoaep(const void *channelContext) {
69937 return UA_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
69938}
69939
69940static size_t
69941sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep(const void *channelContext) {
69942 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_KEY_LENGTH;
69943}
69944
69945static size_t
69946sym_getEncryptionBlockSize_sp_aes128sha256rsaoaep(const void *channelContext) {
69947 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
69948}
69949
69950static size_t
69951sym_getPlainTextBlockSize_sp_aes128sha256rsaoaep(const void *channelContext) {
69952 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE;
69953}
69954
69955static UA_StatusCode
69956sym_encrypt_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
69957 UA_ByteString *data) {
69958 if(cc == NULL || data == NULL)
69959 return UA_STATUSCODE_BADINTERNALERROR;
69960
69961 if(cc->localSymIv.length != UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE)
69962 return UA_STATUSCODE_BADINTERNALERROR;
69963
69964 size_t plainTextBlockSize = UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE;
69965
69966 if(data->length % plainTextBlockSize != 0)
69967 return UA_STATUSCODE_BADINTERNALERROR;
69968
69969 /* Keylength in bits */
69970 unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
69971 mbedtls_aes_context aesContext;
69972 int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
69973 if(mbedErr)
69974 return UA_STATUSCODE_BADINTERNALERROR;
69975
69976 UA_ByteString ivCopy;
69977 UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
69978 if(retval != UA_STATUSCODE_GOOD)
69979 return retval;
69980
69981 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
69982 ivCopy.data, data->data, data->data);
69983 if(mbedErr)
69984 retval = UA_STATUSCODE_BADINTERNALERROR;
69985 UA_ByteString_clear(&ivCopy);
69986 return retval;
69987}
69988
69989static UA_StatusCode
69990sym_decrypt_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
69991 UA_ByteString *data) {
69992 if(cc == NULL || data == NULL)
69993 return UA_STATUSCODE_BADINTERNALERROR;
69994
69995 size_t encryptionBlockSize = UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
69996
69997 if(cc->remoteSymIv.length != encryptionBlockSize)
69998 return UA_STATUSCODE_BADINTERNALERROR;
69999
70000 if(data->length % encryptionBlockSize != 0)
70001 return UA_STATUSCODE_BADINTERNALERROR;
70002
70003 unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
70004 mbedtls_aes_context aesContext;
70005 int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength);
70006 if(mbedErr)
70007 return UA_STATUSCODE_BADINTERNALERROR;
70008
70009 UA_ByteString ivCopy;
70010 UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
70011 if(retval != UA_STATUSCODE_GOOD)
70012 return retval;
70013
70014 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
70015 ivCopy.data, data->data, data->data);
70016 if(mbedErr)
70017 retval = UA_STATUSCODE_BADINTERNALERROR;
70018 UA_ByteString_clear(&ivCopy);
70019 return retval;
70020}
70021
70022static UA_StatusCode
70023sym_generateKey_sp_aes128sha256rsaoaep(void *policyContext, const UA_ByteString *secret,
70024 const UA_ByteString *seed, UA_ByteString *out) {
70025 if(secret == NULL || seed == NULL || out == NULL)
70026 return UA_STATUSCODE_BADINTERNALERROR;
70027 Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)policyContext;
70028 return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out);
70029}
70030
70031static UA_StatusCode
70032sym_generateNonce_sp_aes128sha256rsaoaep(void *policyContext, UA_ByteString *out) {
70033 if(out == NULL)
70034 return UA_STATUSCODE_BADINTERNALERROR;
70035 Aes128Sha256PsaOaep_PolicyContext *pc =
70036 (Aes128Sha256PsaOaep_PolicyContext *)policyContext;
70037 int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
70038 if(mbedErr)
70039 return UA_STATUSCODE_BADUNEXPECTEDERROR;
70040 return UA_STATUSCODE_GOOD;
70041}
70042
70043/*****************/
70044/* ChannelModule */
70045/*****************/
70046
70047/* Assumes that the certificate has been verified externally */
70048static UA_StatusCode
70049parseRemoteCertificate_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70050 const UA_ByteString *remoteCertificate) {
70051 if(remoteCertificate == NULL || cc == NULL)
70052 return UA_STATUSCODE_BADINTERNALERROR;
70053
70054 /* Parse the certificate */
70055 int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
70056 remoteCertificate->length);
70057 if(mbedErr)
70058 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70059
70060 /* Check the key length */
70061#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
70062 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
70063 if(rsaContext->len < UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH ||
70064 rsaContext->len > UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH)
70065#else
70066 size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
70067 if(keylen < UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH ||
70068 keylen > UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH)
70069#endif
70070 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
70071
70072 return UA_STATUSCODE_GOOD;
70073}
70074
70075static void
70076channelContext_deleteContext_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc) {
70077 UA_ByteString_clear(&cc->localSymSigningKey);
70078 UA_ByteString_clear(&cc->localSymEncryptingKey);
70079 UA_ByteString_clear(&cc->localSymIv);
70080
70081 UA_ByteString_clear(&cc->remoteSymSigningKey);
70082 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
70083 UA_ByteString_clear(&cc->remoteSymIv);
70084
70085 mbedtls_x509_crt_free(&cc->remoteCertificate);
70086
70087 UA_free(cc);
70088}
70089
70090static UA_StatusCode
70091channelContext_newContext_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
70092 const UA_ByteString *remoteCertificate,
70093 void **pp_contextData) {
70094 if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
70095 return UA_STATUSCODE_BADINTERNALERROR;
70096
70097 /* Allocate the channel context */
70098 *pp_contextData = UA_malloc(sizeof(Aes128Sha256PsaOaep_ChannelContext));
70099 if(*pp_contextData == NULL)
70100 return UA_STATUSCODE_BADOUTOFMEMORY;
70101
70102 Aes128Sha256PsaOaep_ChannelContext *cc = (Aes128Sha256PsaOaep_ChannelContext *)*pp_contextData;
70103
70104 /* Initialize the channel context */
70105 cc->policyContext = (Aes128Sha256PsaOaep_PolicyContext *)securityPolicy->policyContext;
70106
70107 UA_ByteString_init(&cc->localSymSigningKey);
70108 UA_ByteString_init(&cc->localSymEncryptingKey);
70109 UA_ByteString_init(&cc->localSymIv);
70110
70111 UA_ByteString_init(&cc->remoteSymSigningKey);
70112 UA_ByteString_init(&cc->remoteSymEncryptingKey);
70113 UA_ByteString_init(&cc->remoteSymIv);
70114
70115 mbedtls_x509_crt_init(&cc->remoteCertificate);
70116
70117 // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
70118 UA_StatusCode retval = parseRemoteCertificate_sp_aes128sha256rsaoaep(cc, remoteCertificate);
70119 if(retval != UA_STATUSCODE_GOOD) {
70120 channelContext_deleteContext_sp_aes128sha256rsaoaep(cc);
70121 *pp_contextData = NULL;
70122 }
70123 return retval;
70124}
70125
70126static UA_StatusCode
70127channelContext_setLocalSymEncryptingKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70128 const UA_ByteString *key) {
70129 if(key == NULL || cc == NULL)
70130 return UA_STATUSCODE_BADINTERNALERROR;
70131
70132 UA_ByteString_clear(&cc->localSymEncryptingKey);
70133 return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
70134}
70135
70136static UA_StatusCode
70137channelContext_setLocalSymSigningKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70138 const UA_ByteString *key) {
70139 if(key == NULL || cc == NULL)
70140 return UA_STATUSCODE_BADINTERNALERROR;
70141
70142 UA_ByteString_clear(&cc->localSymSigningKey);
70143 return UA_ByteString_copy(key, &cc->localSymSigningKey);
70144}
70145
70146
70147static UA_StatusCode
70148channelContext_setLocalSymIv_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70149 const UA_ByteString *iv) {
70150 if(iv == NULL || cc == NULL)
70151 return UA_STATUSCODE_BADINTERNALERROR;
70152
70153 UA_ByteString_clear(&cc->localSymIv);
70154 return UA_ByteString_copy(iv, &cc->localSymIv);
70155}
70156
70157static UA_StatusCode
70158channelContext_setRemoteSymEncryptingKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70159 const UA_ByteString *key) {
70160 if(key == NULL || cc == NULL)
70161 return UA_STATUSCODE_BADINTERNALERROR;
70162
70163 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
70164 return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
70165}
70166
70167static UA_StatusCode
70168channelContext_setRemoteSymSigningKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70169 const UA_ByteString *key) {
70170 if(key == NULL || cc == NULL)
70171 return UA_STATUSCODE_BADINTERNALERROR;
70172
70173 UA_ByteString_clear(&cc->remoteSymSigningKey);
70174 return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
70175}
70176
70177static UA_StatusCode
70178channelContext_setRemoteSymIv_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70179 const UA_ByteString *iv) {
70180 if(iv == NULL || cc == NULL)
70181 return UA_STATUSCODE_BADINTERNALERROR;
70182
70183 UA_ByteString_clear(&cc->remoteSymIv);
70184 return UA_ByteString_copy(iv, &cc->remoteSymIv);
70185}
70186
70187static UA_StatusCode
70188channelContext_compareCertificate_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
70189 const UA_ByteString *certificate) {
70190 if(cc == NULL || certificate == NULL)
70191 return UA_STATUSCODE_BADINTERNALERROR;
70192
70193 mbedtls_x509_crt cert;
70194 mbedtls_x509_crt_init(&cert);
70195 int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
70196 if(mbedErr)
70197 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70198
70199 UA_StatusCode retval = UA_STATUSCODE_GOOD;
70200 if(cert.raw.len != cc->remoteCertificate.raw.len ||
70201 memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
70202 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70203
70204 mbedtls_x509_crt_free(&cert);
70205 return retval;
70206}
70207
70208static void
70209clear_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy) {
70210 if(securityPolicy == NULL)
70211 return;
70212
70213 UA_ByteString_clear(&securityPolicy->localCertificate);
70214
70215 if(securityPolicy->policyContext == NULL)
70216 return;
70217
70218 /* delete all allocated members in the context */
70219 Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)
70220 securityPolicy->policyContext;
70221
70222 mbedtls_ctr_drbg_free(&pc->drbgContext);
70223 mbedtls_entropy_free(&pc->entropyContext);
70224 mbedtls_pk_free(&pc->localPrivateKey);
70225 mbedtls_md_free(&pc->sha256MdContext);
70226 UA_ByteString_clear(&pc->localCertThumbprint);
70227
70228 UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
70229 "Deleted members of EndpointContext for sp_aes128sha256rsaoaep");
70230
70231 UA_free(pc);
70232 securityPolicy->policyContext = NULL;
70233}
70234
70235static UA_StatusCode
70236updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy,
70237 const UA_ByteString newCertificate,
70238 const UA_ByteString newPrivateKey) {
70239 if(securityPolicy == NULL)
70240 return UA_STATUSCODE_BADINTERNALERROR;
70241
70242 if(securityPolicy->policyContext == NULL)
70243 return UA_STATUSCODE_BADINTERNALERROR;
70244
70245 Aes128Sha256PsaOaep_PolicyContext *pc =
70246 (Aes128Sha256PsaOaep_PolicyContext *) securityPolicy->policyContext;
70247
70248 UA_ByteString_clear(&securityPolicy->localCertificate);
70249
70250 UA_StatusCode retval = UA_ByteString_allocBuffer(&securityPolicy->localCertificate,
70251 newCertificate.length + 1);
70252 if(retval != UA_STATUSCODE_GOOD)
70253 return retval;
70254 memcpy(securityPolicy->localCertificate.data, newCertificate.data, newCertificate.length);
70255 securityPolicy->localCertificate.data[newCertificate.length] = '\0';
70256 securityPolicy->localCertificate.length--;
70257
70258 /* Set the new private key */
70259 mbedtls_pk_free(&pc->localPrivateKey);
70260 mbedtls_pk_init(&pc->localPrivateKey);
70261#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
70262 int mbedErr = mbedtls_pk_parse_key(&pc->localPrivateKey, newPrivateKey.data,
70263 newPrivateKey.length, NULL, 0);
70264#else
70265 int mbedErr = mbedtls_pk_parse_key(&pc->localPrivateKey, newPrivateKey.data,
70266 newPrivateKey.length, NULL, 0, mbedtls_entropy_func, &pc->drbgContext);
70267#endif
70268 if(mbedErr) {
70269 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70270 goto error;
70271 }
70272
70273 retval = asym_makeThumbprint_sp_aes128sha256rsaoaep(securityPolicy,
70274 &securityPolicy->localCertificate,
70275 &pc->localCertThumbprint);
70276 if(retval != UA_STATUSCODE_GOOD)
70277 goto error;
70278
70279 return retval;
70280
70281 error:
70282 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
70283 "Could not update certificate and private key");
70284 if(securityPolicy->policyContext != NULL)
70285 clear_sp_aes128sha256rsaoaep(securityPolicy);
70286 return retval;
70287}
70288
70289static UA_StatusCode
70290policyContext_newContext_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy,
70291 const UA_ByteString localPrivateKey) {
70292 UA_StatusCode retval = UA_STATUSCODE_GOOD;
70293 if(securityPolicy == NULL)
70294 return UA_STATUSCODE_BADINTERNALERROR;
70295
70296 if (localPrivateKey.length == 0) {
70297 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
70298 "Can not initialize security policy. Private key is empty.");
70299 return UA_STATUSCODE_BADINVALIDARGUMENT;
70300 }
70301
70302 Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)
70303 UA_malloc(sizeof(Aes128Sha256PsaOaep_PolicyContext));
70304 securityPolicy->policyContext = (void *)pc;
70305 if(!pc) {
70306 retval = UA_STATUSCODE_BADOUTOFMEMORY;
70307 goto error;
70308 }
70309
70310 /* Initialize the PolicyContext */
70311 memset(pc, 0, sizeof(Aes128Sha256PsaOaep_PolicyContext));
70312 mbedtls_ctr_drbg_init(&pc->drbgContext);
70313 mbedtls_entropy_init(&pc->entropyContext);
70314 mbedtls_pk_init(&pc->localPrivateKey);
70315 mbedtls_md_init(&pc->sha256MdContext);
70316
70317 /* Initialized the message digest */
70318 const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
70319 int mbedErr = mbedtls_md_setup(&pc->sha256MdContext, mdInfo, MBEDTLS_MD_SHA256);
70320 if(mbedErr) {
70321 retval = UA_STATUSCODE_BADOUTOFMEMORY;
70322 goto error;
70323 }
70324
70325 mbedErr = mbedtls_entropy_self_test(0);
70326
70327 if(mbedErr) {
70328 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70329 goto error;
70330 }
70331
70332 /* Seed the RNG */
70333 char *personalization = "open62541-drbg";
70334 mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
70335 &pc->entropyContext,
70336 (const unsigned char *)personalization, 14);
70337 if(mbedErr) {
70338 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70339 goto error;
70340 }
70341
70342 /* Set the private key */
70343 mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
70344 if(mbedErr) {
70345 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70346 goto error;
70347 }
70348
70349 /* Set the local certificate thumbprint */
70350 retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
70351 if(retval != UA_STATUSCODE_GOOD)
70352 goto error;
70353 retval = asym_makeThumbprint_sp_aes128sha256rsaoaep(securityPolicy,
70354 &securityPolicy->localCertificate,
70355 &pc->localCertThumbprint);
70356 if(retval != UA_STATUSCODE_GOOD)
70357 goto error;
70358
70359 return UA_STATUSCODE_GOOD;
70360
70361error:
70362 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
70363 "Could not create securityContext: %s", UA_StatusCode_name(retval));
70364 if(securityPolicy->policyContext != NULL)
70365 clear_sp_aes128sha256rsaoaep(securityPolicy);
70366 return retval;
70367}
70368
70369UA_StatusCode
70370UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
70371 const UA_ByteString localPrivateKey, const UA_Logger *logger) {
70372 memset(policy, 0, sizeof(UA_SecurityPolicy));
70373 policy->logger = logger;
70374
70375 policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep");
70376
70377 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
70378 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
70379 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
70380
70381 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
70382
70383 if (retval != UA_STATUSCODE_GOOD)
70384 return retval;
70385
70386 /* AsymmetricModule */
70387 UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
70388 &asymmetricModule->cryptoModule.signatureAlgorithm;
70389 asym_signatureAlgorithm->uri =
70390 UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
70391 asym_signatureAlgorithm->verify =
70392 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_aes128sha256rsaoaep;
70393 asym_signatureAlgorithm->sign =
70394 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_aes128sha256rsaoaep;
70395 asym_signatureAlgorithm->getLocalSignatureSize =
70396 (size_t (*)(const void *))asym_getLocalSignatureSize_sp_aes128sha256rsaoaep;
70397 asym_signatureAlgorithm->getRemoteSignatureSize =
70398 (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_aes128sha256rsaoaep;
70399 asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
70400 asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
70401
70402 UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
70403 &asymmetricModule->cryptoModule.encryptionAlgorithm;
70404 asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
70405 asym_encryptionAlgorithm->encrypt =
70406 (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_aes128sha256rsaoaep;
70407 asym_encryptionAlgorithm->decrypt =
70408 (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_aes128sha256rsaoaep;
70409 asym_encryptionAlgorithm->getLocalKeyLength =
70410 (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_aes128sha256rsaoaep;
70411 asym_encryptionAlgorithm->getRemoteKeyLength =
70412 (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_aes128sha256rsaoaep;
70413 asym_encryptionAlgorithm->getRemoteBlockSize = (size_t (*)(const void *))asym_getRemoteBlockSize_sp_aes128sha256rsaoaep;
70414 asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
70415 (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep;
70416
70417 asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_aes128sha256rsaoaep;
70418 asymmetricModule->compareCertificateThumbprint =
70419 asymmetricModule_compareCertificateThumbprint_sp_aes128sha256rsaoaep;
70420
70421 /* SymmetricModule */
70422 symmetricModule->generateKey = sym_generateKey_sp_aes128sha256rsaoaep;
70423 symmetricModule->generateNonce = sym_generateNonce_sp_aes128sha256rsaoaep;
70424
70425 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
70426 &symmetricModule->cryptoModule.signatureAlgorithm;
70427 sym_signatureAlgorithm->uri =
70428 UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
70429 sym_signatureAlgorithm->verify =
70430 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_aes128sha256rsaoaep;
70431 sym_signatureAlgorithm->sign =
70432 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_aes128sha256rsaoaep;
70433 sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_aes128sha256rsaoaep;
70434 sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_aes128sha256rsaoaep;
70435 sym_signatureAlgorithm->getLocalKeyLength =
70436 (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes128sha256rsaoaep;
70437 sym_signatureAlgorithm->getRemoteKeyLength =
70438 (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes128sha256rsaoaep;
70439
70440 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
70441 &symmetricModule->cryptoModule.encryptionAlgorithm;
70442 sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
70443 sym_encryptionAlgorithm->encrypt =
70444 (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_aes128sha256rsaoaep;
70445 sym_encryptionAlgorithm->decrypt =
70446 (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_aes128sha256rsaoaep;
70447 sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep;
70448 sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep;
70449 sym_encryptionAlgorithm->getRemoteBlockSize =
70450 (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_aes128sha256rsaoaep;
70451 sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
70452 (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_aes128sha256rsaoaep;
70453 symmetricModule->secureChannelNonceLength = 32;
70454
70455 // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
70456 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
70457
70458 /* ChannelModule */
70459 channelModule->newContext = channelContext_newContext_sp_aes128sha256rsaoaep;
70460 channelModule->deleteContext = (void (*)(void *))
70461 channelContext_deleteContext_sp_aes128sha256rsaoaep;
70462
70463 channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
70464 channelContext_setLocalSymEncryptingKey_sp_aes128sha256rsaoaep;
70465 channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
70466 channelContext_setLocalSymSigningKey_sp_aes128sha256rsaoaep;
70467 channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
70468 channelContext_setLocalSymIv_sp_aes128sha256rsaoaep;
70469
70470 channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
70471 channelContext_setRemoteSymEncryptingKey_sp_aes128sha256rsaoaep;
70472 channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
70473 channelContext_setRemoteSymSigningKey_sp_aes128sha256rsaoaep;
70474 channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
70475 channelContext_setRemoteSymIv_sp_aes128sha256rsaoaep;
70476
70477 channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
70478 channelContext_compareCertificate_sp_aes128sha256rsaoaep;
70479
70480 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep;
70481 policy->clear = clear_sp_aes128sha256rsaoaep;
70482
70483 UA_StatusCode res = policyContext_newContext_sp_aes128sha256rsaoaep(policy, localPrivateKey);
70484 if(res != UA_STATUSCODE_GOOD)
70485 clear_sp_aes128sha256rsaoaep(policy);
70486
70487 return res;
70488}
70489
70490#endif
70491
70492/**** amalgamated original file "/plugins/crypto/mbedtls/ua_pki_mbedtls.c" ****/
70493
70494/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
70495 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
70496 *
70497 * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
70498 * Copyright 2019 (c) Kalycito Infotech Private Limited
70499 * Copyright 2019 (c) Julius Pfrommer, Fraunhofer IOSB
70500 */
70501
70502
70503#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
70504
70505#include <mbedtls/x509.h>
70506#include <mbedtls/x509_crt.h>
70507#include <mbedtls/error.h>
70508#include <mbedtls/version.h>
70509
70510#define REMOTECERTIFICATETRUSTED 1
70511#define ISSUERKNOWN 2
70512#define DUALPARENT 3
70513#define PARENTFOUND 4
70514
70515/* Find binary substring. Taken and adjusted from
70516 * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */
70517
70518static const unsigned char *
70519bstrchr(const unsigned char *s, const unsigned char ch, size_t l) {
70520 /* find first occurrence of c in char s[] for length l*/
70521 for(; l > 0; ++s, --l) {
70522 if(*s == ch)
70523 return s;
70524 }
70525 return NULL;
70526}
70527
70528static const unsigned char *
70529UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) {
70530 /* find first occurrence of s2[] in s1[] for length l1*/
70531 const unsigned char *ss1 = s1;
70532 const unsigned char *ss2 = s2;
70533 /* handle special case */
70534 if(l1 == 0)
70535 return (NULL);
70536 if(l2 == 0)
70537 return s1;
70538
70539 /* match prefix */
70540 for (; (s1 = bstrchr(s1, *s2, (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL &&
70541 (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) {
70542
70543 /* match rest of prefix */
70544 const unsigned char *sc1, *sc2;
70545 for (sc1 = s1, sc2 = s2; ;)
70546 if (++sc2 >= ss2+l2)
70547 return s1;
70548 else if (*++sc1 != *sc2)
70549 break;
70550 }
70551 return NULL;
70552}
70553
70554// mbedTLS expects PEM data to be null terminated
70555// The data length parameter must include the null terminator
70556static UA_ByteString copyDataFormatAware(const UA_ByteString *data)
70557{
70558 UA_ByteString result;
70559 UA_ByteString_init(&result);
70560
70561 if (!data->length)
70562 return result;
70563
70564 if (data->length && data->data[0] == '-') {
70565 UA_ByteString_allocBuffer(&result, data->length + 1);
70566 memcpy(result.data, data->data, data->length);
70567 result.data[data->length] = '\0';
70568 } else {
70569 UA_ByteString_copy(data, &result);
70570 }
70571
70572 return result;
70573}
70574
70575typedef struct {
70576 /* If the folders are defined, we use them to reload the certificates during
70577 * runtime */
70578 UA_String trustListFolder;
70579 UA_String issuerListFolder;
70580 UA_String revocationListFolder;
70581
70582 mbedtls_x509_crt certificateTrustList;
70583 mbedtls_x509_crt certificateIssuerList;
70584 mbedtls_x509_crl certificateRevocationList;
70585} CertInfo;
70586
70587#ifdef __linux__ /* Linux only so far */
70588
70589#include <dirent.h>
70590#include <limits.h>
70591
70592static UA_StatusCode
70593fileNamesFromFolder(const UA_String *folder, size_t *pathsSize, UA_String **paths) {
70594 char buf[PATH_MAX + 1];
70595 if(folder->length > PATH_MAX)
70596 return UA_STATUSCODE_BADINTERNALERROR;
70597
70598 memcpy(buf, folder->data, folder->length);
70599 buf[folder->length] = 0;
70600
70601 DIR *dir = opendir(buf);
70602 if(!dir)
70603 return UA_STATUSCODE_BADINTERNALERROR;
70604
70605 *paths = (UA_String*)UA_Array_new(256, &UA_TYPES[UA_TYPES_STRING]);
70606 if(*paths == NULL) {
70607 closedir(dir);
70608 return UA_STATUSCODE_BADOUTOFMEMORY;
70609 }
70610
70611 struct dirent *ent;
70612 char buf2[PATH_MAX + 1];
70613 char *res = realpath(buf, buf2);
70614 if(!res) {
70615 closedir(dir);
70616 return UA_STATUSCODE_BADINTERNALERROR;
70617 }
70618 size_t pathlen = strlen(buf2);
70619 *pathsSize = 0;
70620 while((ent = readdir (dir)) != NULL && *pathsSize < 256) {
70621 if(ent->d_type != DT_REG)
70622 continue;
70623 buf2[pathlen] = '/';
70624 buf2[pathlen+1] = 0;
70625 strcat(buf2, ent->d_name);
70626 (*paths)[*pathsSize] = UA_STRING_ALLOC(buf2);
70627 *pathsSize += 1;
70628 }
70629 closedir(dir);
70630
70631 if(*pathsSize == 0) {
70632 UA_free(*paths);
70633 *paths = NULL;
70634 }
70635 return UA_STATUSCODE_GOOD;
70636}
70637
70638static UA_StatusCode
70639reloadCertificates(CertInfo *ci) {
70640 UA_StatusCode retval = UA_STATUSCODE_GOOD;
70641 int err = 0;
70642 int internalErrorFlag = 0;
70643
70644 /* Load the trustlists */
70645 if(ci->trustListFolder.length > 0) {
70646 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the trust-list");
70647 mbedtls_x509_crt_free(&ci->certificateTrustList);
70648 mbedtls_x509_crt_init(&ci->certificateTrustList);
70649
70650 char f[PATH_MAX];
70651 memcpy(f, ci->trustListFolder.data, ci->trustListFolder.length);
70652 f[ci->trustListFolder.length] = 0;
70653 err = mbedtls_x509_crt_parse_path(&ci->certificateTrustList, f);
70654 if(err == 0) {
70655 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70656 "Loaded certificate from %s", f);
70657 } else {
70658 char errBuff[300];
70659 mbedtls_strerror(err, errBuff, 300);
70660 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70661 "Failed to load certificate from %s, mbedTLS error: %s (error code: %d)", f, errBuff, err);
70662 internalErrorFlag = 1;
70663 }
70664 }
70665
70666 /* Load the revocationlists */
70667 if(ci->revocationListFolder.length > 0) {
70668 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the revocation-list");
70669 size_t pathsSize = 0;
70670 UA_String *paths = NULL;
70671 retval = fileNamesFromFolder(&ci->revocationListFolder, &pathsSize, &paths);
70672 if(retval != UA_STATUSCODE_GOOD)
70673 return retval;
70674 mbedtls_x509_crl_free(&ci->certificateRevocationList);
70675 mbedtls_x509_crl_init(&ci->certificateRevocationList);
70676 for(size_t i = 0; i < pathsSize; i++) {
70677 char f[PATH_MAX];
70678 memcpy(f, paths[i].data, paths[i].length);
70679 f[paths[i].length] = 0;
70680 err = mbedtls_x509_crl_parse_file(&ci->certificateRevocationList, f);
70681 if(err == 0) {
70682 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70683 "Loaded certificate from %.*s",
70684 (int)paths[i].length, paths[i].data);
70685 } else {
70686 char errBuff[300];
70687 mbedtls_strerror(err, errBuff, 300);
70688 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70689 "Failed to load certificate from %.*s, mbedTLS error: %s (error code: %d)",
70690 (int)paths[i].length, paths[i].data, errBuff, err);
70691 internalErrorFlag = 1;
70692 }
70693 }
70694 UA_Array_delete(paths, pathsSize, &UA_TYPES[UA_TYPES_STRING]);
70695 paths = NULL;
70696 pathsSize = 0;
70697 }
70698
70699 /* Load the issuerlists */
70700 if(ci->issuerListFolder.length > 0) {
70701 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the issuer-list");
70702 mbedtls_x509_crt_free(&ci->certificateIssuerList);
70703 mbedtls_x509_crt_init(&ci->certificateIssuerList);
70704 char f[PATH_MAX];
70705 memcpy(f, ci->issuerListFolder.data, ci->issuerListFolder.length);
70706 f[ci->issuerListFolder.length] = 0;
70707 err = mbedtls_x509_crt_parse_path(&ci->certificateIssuerList, f);
70708 if(err == 0) {
70709 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70710 "Loaded certificate from %s", f);
70711 } else {
70712 char errBuff[300];
70713 mbedtls_strerror(err, errBuff, 300);
70714 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70715 "Failed to load certificate from %s, mbedTLS error: %s (error code: %d)",
70716 f, errBuff, err);
70717 internalErrorFlag = 1;
70718 }
70719 }
70720
70721 if(internalErrorFlag) {
70722 retval = UA_STATUSCODE_BADINTERNALERROR;
70723 }
70724 return retval;
70725}
70726
70727#endif
70728
70729static UA_StatusCode
70730certificateVerification_verify(void *verificationContext,
70731 const UA_ByteString *certificate) {
70732 CertInfo *ci = (CertInfo*)verificationContext;
70733 if(!ci)
70734 return UA_STATUSCODE_BADINTERNALERROR;
70735
70736#ifdef __linux__ /* Reload certificates if folder paths are specified */
70737 UA_StatusCode certFlag = reloadCertificates(ci);
70738 if(certFlag != UA_STATUSCODE_GOOD) {
70739 return certFlag;
70740 }
70741#endif
70742
70743 if(ci->trustListFolder.length == 0 &&
70744 ci->issuerListFolder.length == 0 &&
70745 ci->revocationListFolder.length == 0 &&
70746 ci->certificateTrustList.raw.len == 0 &&
70747 ci->certificateIssuerList.raw.len == 0 &&
70748 ci->certificateRevocationList.raw.len == 0) {
70749 UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70750 "PKI plugin unconfigured. Accepting the certificate.");
70751 return UA_STATUSCODE_GOOD;
70752 }
70753
70754 /* Parse the certificate */
70755 mbedtls_x509_crt remoteCertificate;
70756
70757 /* Temporary Object to parse the trustList */
70758 mbedtls_x509_crt *tempCert = NULL;
70759
70760 /* Temporary Object to parse the revocationList */
70761 mbedtls_x509_crl *tempCrl = NULL;
70762
70763 /* Temporary Object to identify the parent CA when there is no intermediate CA */
70764 mbedtls_x509_crt *parentCert = NULL;
70765
70766 /* Temporary Object to identify the parent CA when there is intermediate CA */
70767 mbedtls_x509_crt *parentCert_2 = NULL;
70768
70769 /* Flag value to identify if the issuer certificate is found */
70770 int issuerKnown = 0;
70771
70772 /* Flag value to identify if the parent certificate found */
70773 int parentFound = 0;
70774
70775 mbedtls_x509_crt_init(&remoteCertificate);
70776 int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
70777 certificate->length);
70778 if(mbedErr) {
70779 /* char errBuff[300]; */
70780 /* mbedtls_strerror(mbedErr, errBuff, 300); */
70781 /* UA_LOG_WARNING(data->policyContext->securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, */
70782 /* "Could not parse the remote certificate with error: %s", errBuff); */
70783 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70784 }
70785
70786 /* Verify */
70787 mbedtls_x509_crt_profile crtProfile = {
70788 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256),
70789 0xFFFFFF, 0x000000, 128 * 8 // in bits
70790 }; // TODO: remove magic numbers
70791
70792 uint32_t flags = 0;
70793 mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
70794 &ci->certificateTrustList,
70795 &ci->certificateRevocationList,
70796 &crtProfile, NULL, &flags, NULL, NULL);
70797
70798 /* Flag to check if the remote certificate is trusted or not */
70799 int TRUSTED = 0;
70800
70801 /* Check if the remoteCertificate is present in the trustList while mbedErr value is not zero */
70802 if(mbedErr && !(flags & MBEDTLS_X509_BADCERT_EXPIRED) && !(flags & MBEDTLS_X509_BADCERT_FUTURE)) {
70803 for(tempCert = &ci->certificateTrustList; tempCert != NULL; tempCert = tempCert->next) {
70804 if(remoteCertificate.raw.len == tempCert->raw.len &&
70805 memcmp(remoteCertificate.raw.p, tempCert->raw.p, remoteCertificate.raw.len) == 0) {
70806 TRUSTED = REMOTECERTIFICATETRUSTED;
70807 break;
70808 }
70809 }
70810 }
70811
70812 /* If the remote certificate is present in the trustList then check if the issuer certificate
70813 * of remoteCertificate is present in issuerList */
70814 if(TRUSTED && mbedErr) {
70815 mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
70816 &ci->certificateIssuerList,
70817 &ci->certificateRevocationList,
70818 &crtProfile, NULL, &flags, NULL, NULL);
70819
70820 /* Check if the parent certificate has a CRL file available */
70821 if(!mbedErr) {
70822 /* Flag value to identify if that there is an intermediate CA present */
70823 int dualParent = 0;
70824
70825 /* Identify the topmost parent certificate for the remoteCertificate */
70826 for(parentCert = &ci->certificateIssuerList; parentCert != NULL; parentCert = parentCert->next ) {
70827 if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) {
70828 for(parentCert_2 = &ci->certificateTrustList; parentCert_2 != NULL; parentCert_2 = parentCert_2->next) {
70829 if(memcmp(parentCert->issuer_raw.p, parentCert_2->subject_raw.p, parentCert_2->subject_raw.len) == 0) {
70830 dualParent = DUALPARENT;
70831 break;
70832 }
70833 }
70834 parentFound = PARENTFOUND;
70835 }
70836
70837 if(parentFound == PARENTFOUND)
70838 break;
70839 }
70840
70841 /* Check if there is an intermediate certificate between the topmost parent
70842 * certificate and child certificate
70843 * If yes the topmost parent certificate is to be checked whether it has a
70844 * CRL file avaiable */
70845 if(dualParent == DUALPARENT && parentFound == PARENTFOUND) {
70846 parentCert = parentCert_2;
70847 }
70848
70849 /* If a parent certificate is found traverse the revocationList and identify
70850 * if there is any CRL file that corresponds to the parentCertificate */
70851 if(parentFound == PARENTFOUND) {
70852 tempCrl = &ci->certificateRevocationList;
70853 while(tempCrl != NULL) {
70854 if(tempCrl->version != 0 &&
70855 tempCrl->issuer_raw.len == parentCert->subject_raw.len &&
70856 memcmp(tempCrl->issuer_raw.p,
70857 parentCert->subject_raw.p,
70858 tempCrl->issuer_raw.len) == 0) {
70859 issuerKnown = ISSUERKNOWN;
70860 break;
70861 }
70862
70863 tempCrl = tempCrl->next;
70864 }
70865
70866 /* If the CRL file corresponding to the parent certificate is not present
70867 * then return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN */
70868 if(!issuerKnown) {
70869 return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN;
70870 }
70871
70872 }
70873
70874 }
70875
70876 }
70877 else if(!mbedErr && !TRUSTED) {
70878 /* This else if section is to identify if the parent certificate which is present in trustList
70879 * has CRL file corresponding to it */
70880
70881 /* Identify the parent certificate of the remoteCertificate */
70882 for(parentCert = &ci->certificateTrustList; parentCert != NULL; parentCert = parentCert->next) {
70883 if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) {
70884 parentFound = PARENTFOUND;
70885 break;
70886 }
70887
70888 }
70889
70890 /* If the parent certificate is found traverse the revocationList and identify
70891 * if there is any CRL file that corresponds to the parentCertificate */
70892 if(parentFound == PARENTFOUND &&
70893 memcmp(remoteCertificate.issuer_raw.p, remoteCertificate.subject_raw.p, remoteCertificate.subject_raw.len) != 0) {
70894 tempCrl = &ci->certificateRevocationList;
70895 while(tempCrl != NULL) {
70896 if(tempCrl->version != 0 &&
70897 tempCrl->issuer_raw.len == parentCert->subject_raw.len &&
70898 memcmp(tempCrl->issuer_raw.p,
70899 parentCert->subject_raw.p,
70900 tempCrl->issuer_raw.len) == 0) {
70901 issuerKnown = ISSUERKNOWN;
70902 break;
70903 }
70904
70905 tempCrl = tempCrl->next;
70906 }
70907
70908 /* If the CRL file corresponding to the parent certificate is not present
70909 * then return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN */
70910 if(!issuerKnown) {
70911 return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN;
70912 }
70913
70914 }
70915
70916 }
70917
70918 // TODO: Extend verification
70919
70920 /* This condition will check whether the certificate is a User certificate
70921 * or a CA certificate. If the MBEDTLS_X509_KU_KEY_CERT_SIGN and
70922 * MBEDTLS_X509_KU_CRL_SIGN of key_usage are set, then the certificate
70923 * shall be condidered as CA Certificate and cannot be used to establish a
70924 * connection. Refer the test case CTT/Security/Security Certificate Validation/029.js
70925 * for more details */
70926#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
70927 if((remoteCertificate.key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
70928 (remoteCertificate.key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
70929 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
70930 }
70931#else
70932 if((remoteCertificate.private_key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
70933 (remoteCertificate.private_key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
70934 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
70935 }
70936#endif
70937
70938
70939 UA_StatusCode retval = UA_STATUSCODE_GOOD;
70940 if(mbedErr) {
70941#if UA_LOGLEVEL <= 400
70942 char buff[100];
70943 int len = mbedtls_x509_crt_verify_info(buff, 100, "", flags);
70944 UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SECURITYPOLICY,
70945 "Verifying the certificate failed with error: %.*s", len-1, buff);
70946#endif
70947 if(flags & (uint32_t)MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
70948 retval = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
70949 } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_FUTURE ||
70950 flags & (uint32_t)MBEDTLS_X509_BADCERT_EXPIRED) {
70951 retval = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
70952 } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_REVOKED ||
70953 flags & (uint32_t)MBEDTLS_X509_BADCRL_EXPIRED) {
70954 retval = UA_STATUSCODE_BADCERTIFICATEREVOKED;
70955 } else {
70956 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70957 }
70958 }
70959
70960 mbedtls_x509_crt_free(&remoteCertificate);
70961 return retval;
70962}
70963
70964static UA_StatusCode
70965certificateVerification_verifyApplicationURI(void *verificationContext,
70966 const UA_ByteString *certificate,
70967 const UA_String *applicationURI) {
70968 CertInfo *ci = (CertInfo*)verificationContext;
70969 if(!ci)
70970 return UA_STATUSCODE_BADINTERNALERROR;
70971
70972 /* Parse the certificate */
70973 mbedtls_x509_crt remoteCertificate;
70974 mbedtls_x509_crt_init(&remoteCertificate);
70975 int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
70976 certificate->length);
70977 if(mbedErr)
70978 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70979
70980 /* Poor man's ApplicationUri verification. mbedTLS does not parse all fields
70981 * of the Alternative Subject Name. Instead test whether the URI-string is
70982 * present in the v3_ext field in general.
70983 *
70984 * TODO: Improve parsing of the Alternative Subject Name */
70985 UA_StatusCode retval = UA_STATUSCODE_GOOD;
70986 if(UA_Bstrstr(remoteCertificate.v3_ext.p, remoteCertificate.v3_ext.len,
70987 applicationURI->data, applicationURI->length) == NULL)
70988 retval = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
70989
70990 mbedtls_x509_crt_free(&remoteCertificate);
70991 return retval;
70992}
70993
70994static void
70995certificateVerification_clear(UA_CertificateVerification *cv) {
70996 CertInfo *ci = (CertInfo*)cv->context;
70997 if(!ci)
70998 return;
70999 mbedtls_x509_crt_free(&ci->certificateTrustList);
71000 mbedtls_x509_crl_free(&ci->certificateRevocationList);
71001 mbedtls_x509_crt_free(&ci->certificateIssuerList);
71002 UA_String_clear(&ci->trustListFolder);
71003 UA_String_clear(&ci->issuerListFolder);
71004 UA_String_clear(&ci->revocationListFolder);
71005 UA_free(ci);
71006 cv->context = NULL;
71007}
71008
71009UA_StatusCode
71010UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv,
71011 const UA_ByteString *certificateTrustList,
71012 size_t certificateTrustListSize,
71013 const UA_ByteString *certificateIssuerList,
71014 size_t certificateIssuerListSize,
71015 const UA_ByteString *certificateRevocationList,
71016 size_t certificateRevocationListSize) {
71017 CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
71018 if(!ci)
71019 return UA_STATUSCODE_BADOUTOFMEMORY;
71020 memset(ci, 0, sizeof(CertInfo));
71021 mbedtls_x509_crt_init(&ci->certificateTrustList);
71022 mbedtls_x509_crl_init(&ci->certificateRevocationList);
71023 mbedtls_x509_crt_init(&ci->certificateIssuerList);
71024
71025 cv->context = (void*)ci;
71026 cv->verifyCertificate = certificateVerification_verify;
71027 cv->clear = certificateVerification_clear;
71028 cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
71029
71030 int err;
71031 UA_ByteString data;
71032 UA_ByteString_init(&data);
71033
71034 for(size_t i = 0; i < certificateTrustListSize; i++) {
71035 data = copyDataFormatAware(&certificateTrustList[i]);
71036 err = mbedtls_x509_crt_parse(&ci->certificateTrustList,
71037 data.data,
71038 data.length);
71039 UA_ByteString_clear(&data);
71040 if(err)
71041 goto error;
71042 }
71043 for(size_t i = 0; i < certificateIssuerListSize; i++) {
71044 data = copyDataFormatAware(&certificateIssuerList[i]);
71045 err = mbedtls_x509_crt_parse(&ci->certificateIssuerList,
71046 data.data,
71047 data.length);
71048 UA_ByteString_clear(&data);
71049 if(err)
71050 goto error;
71051 }
71052 for(size_t i = 0; i < certificateRevocationListSize; i++) {
71053 data = copyDataFormatAware(&certificateRevocationList[i]);
71054 err = mbedtls_x509_crl_parse(&ci->certificateRevocationList,
71055 data.data,
71056 data.length);
71057 UA_ByteString_clear(&data);
71058 if(err)
71059 goto error;
71060 }
71061
71062 return UA_STATUSCODE_GOOD;
71063error:
71064 certificateVerification_clear(cv);
71065 return UA_STATUSCODE_BADINTERNALERROR;
71066}
71067
71068#ifdef __linux__ /* Linux only so far */
71069
71070UA_StatusCode
71071UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv,
71072 const char *trustListFolder,
71073 const char *issuerListFolder,
71074 const char *revocationListFolder) {
71075 CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
71076 if(!ci)
71077 return UA_STATUSCODE_BADOUTOFMEMORY;
71078 memset(ci, 0, sizeof(CertInfo));
71079 mbedtls_x509_crt_init(&ci->certificateTrustList);
71080 mbedtls_x509_crl_init(&ci->certificateRevocationList);
71081 mbedtls_x509_crt_init(&ci->certificateIssuerList);
71082
71083 /* Only set the folder paths. They will be reloaded during runtime.
71084 * TODO: Add a more efficient reloading of only the changes */
71085 ci->trustListFolder = UA_STRING_ALLOC(trustListFolder);
71086 ci->issuerListFolder = UA_STRING_ALLOC(issuerListFolder);
71087 ci->revocationListFolder = UA_STRING_ALLOC(revocationListFolder);
71088
71089 reloadCertificates(ci);
71090
71091 cv->context = (void*)ci;
71092 cv->verifyCertificate = certificateVerification_verify;
71093 cv->clear = certificateVerification_clear;
71094 cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
71095
71096 return UA_STATUSCODE_GOOD;
71097}
71098
71099#endif
71100#endif
71101
71102/**** amalgamated original file "/plugins/crypto/mbedtls/securitypolicy_mbedtls_common.c" ****/
71103
71104
71105#if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_PUBSUB_ENCRYPTION)
71106
71107
71108#include <mbedtls/aes.h>
71109#include <mbedtls/ctr_drbg.h>
71110#include <mbedtls/entropy.h>
71111#include <mbedtls/error.h>
71112#include <mbedtls/md.h>
71113#include <mbedtls/sha1.h>
71114#include <mbedtls/version.h>
71115#include <mbedtls/x509_crt.h>
71116
71117void
71118swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB) {
71119 UA_ByteString tmp = *bufA;
71120 *bufA = *bufB;
71121 *bufB = tmp;
71122}
71123
71124void
71125mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
71126 const UA_ByteString *in, unsigned char *out) {
71127 mbedtls_md_hmac_starts(context, key->data, key->length);
71128 mbedtls_md_hmac_update(context, in->data, in->length);
71129 mbedtls_md_hmac_finish(context, out);
71130}
71131
71132UA_StatusCode
71133mbedtls_generateKey(mbedtls_md_context_t *context,
71134 const UA_ByteString *secret, const UA_ByteString *seed,
71135 UA_ByteString *out) {
71136#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71137 size_t hashLen = (size_t)mbedtls_md_get_size(context->md_info);
71138#else
71139 size_t hashLen = (size_t)mbedtls_md_get_size(context->private_md_info);
71140#endif
71141
71142 UA_ByteString A_and_seed;
71143 UA_ByteString_allocBuffer(&A_and_seed, hashLen + seed->length);
71144 memcpy(A_and_seed.data + hashLen, seed->data, seed->length);
71145
71146 UA_ByteString ANext_and_seed;
71147 UA_ByteString_allocBuffer(&ANext_and_seed, hashLen + seed->length);
71148 memcpy(ANext_and_seed.data + hashLen, seed->data, seed->length);
71149
71150 UA_ByteString A = {
71151 hashLen,
71152 A_and_seed.data
71153 };
71154
71155 UA_ByteString ANext = {
71156 hashLen,
71157 ANext_and_seed.data
71158 };
71159
71160 mbedtls_hmac(context, secret, seed, A.data);
71161
71162 UA_StatusCode retval = 0;
71163 for(size_t offset = 0; offset < out->length; offset += hashLen) {
71164 UA_ByteString outSegment = {
71165 hashLen,
71166 out->data + offset
71167 };
71168 UA_Boolean bufferAllocated = UA_FALSE;
71169 // Not enough room in out buffer to write the hash.
71170 if(offset + hashLen > out->length) {
71171 outSegment.data = NULL;
71172 outSegment.length = 0;
71173 retval = UA_ByteString_allocBuffer(&outSegment, hashLen);
71174 if(retval != UA_STATUSCODE_GOOD) {
71175 UA_ByteString_clear(&A_and_seed);
71176 UA_ByteString_clear(&ANext_and_seed);
71177 return retval;
71178 }
71179 bufferAllocated = UA_TRUE;
71180 }
71181
71182 mbedtls_hmac(context, secret, &A_and_seed, outSegment.data);
71183 mbedtls_hmac(context, secret, &A, ANext.data);
71184
71185 if(retval != UA_STATUSCODE_GOOD) {
71186 if(bufferAllocated)
71187 UA_ByteString_clear(&outSegment);
71188 UA_ByteString_clear(&A_and_seed);
71189 UA_ByteString_clear(&ANext_and_seed);
71190 return retval;
71191 }
71192
71193 if(bufferAllocated) {
71194 memcpy(out->data + offset, outSegment.data, out->length - offset);
71195 UA_ByteString_clear(&outSegment);
71196 }
71197
71198 swapBuffers(&ANext_and_seed, &A_and_seed);
71199 swapBuffers(&ANext, &A);
71200 }
71201
71202 UA_ByteString_clear(&A_and_seed);
71203 UA_ByteString_clear(&ANext_and_seed);
71204 return UA_STATUSCODE_GOOD;
71205}
71206
71207UA_StatusCode
71208mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message,
71209 const UA_ByteString *signature) {
71210 /* Compute the sha1 hash */
71211 unsigned char hash[UA_SHA1_LENGTH];
71212#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71213 mbedtls_sha1_ret(message->data, message->length, hash);
71214#else
71215 mbedtls_sha1(message->data, message->length, hash);
71216#endif
71217
71218 /* Set the RSA settings */
71219 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(certificate->pk);
71220 if(!rsaContext)
71221 return UA_STATUSCODE_BADINTERNALERROR;
71222 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
71223
71224 /* Verify */
71225 int mbedErr = mbedtls_pk_verify(&certificate->pk,
71226 MBEDTLS_MD_SHA1, hash, UA_SHA1_LENGTH,
71227 signature->data, signature->length);
71228 if(mbedErr)
71229 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
71230 return UA_STATUSCODE_GOOD;
71231}
71232
71233UA_StatusCode
71234mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey,
71235 mbedtls_ctr_drbg_context *drbgContext,
71236 const UA_ByteString *message,
71237 UA_ByteString *signature) {
71238 unsigned char hash[UA_SHA1_LENGTH];
71239#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71240 mbedtls_sha1_ret(message->data, message->length, hash);
71241#else
71242 mbedtls_sha1(message->data, message->length, hash);
71243#endif
71244
71245 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey);
71246 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
71247
71248 size_t sigLen = 0;
71249 int mbedErr = mbedtls_pk_sign(localPrivateKey, MBEDTLS_MD_SHA1, hash,
71250 UA_SHA1_LENGTH, signature->data,
71251#if MBEDTLS_VERSION_NUMBER >= 0x03000000
71252 signature->length,
71253#endif
71254 &sigLen,
71255 mbedtls_ctr_drbg_random, drbgContext);
71256 if(mbedErr)
71257 return UA_STATUSCODE_BADINTERNALERROR;
71258 return UA_STATUSCODE_GOOD;
71259}
71260
71261UA_StatusCode
71262mbedtls_thumbprint_sha1(const UA_ByteString *certificate,
71263 UA_ByteString *thumbprint) {
71264 if(UA_ByteString_equal(certificate, &UA_BYTESTRING_NULL))
71265 return UA_STATUSCODE_BADINTERNALERROR;
71266
71267 if(thumbprint->length != UA_SHA1_LENGTH)
71268 return UA_STATUSCODE_BADINTERNALERROR;
71269
71270 /* The certificate thumbprint is always a 20 bit sha1 hash, see Part 4 of the Specification. */
71271#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71272 mbedtls_sha1_ret(certificate->data, certificate->length, thumbprint->data);
71273#else
71274 mbedtls_sha1(certificate->data, certificate->length, thumbprint->data);
71275#endif
71276 return UA_STATUSCODE_GOOD;
71277}
71278
71279UA_StatusCode
71280mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context,
71281 mbedtls_ctr_drbg_context *drbgContext,
71282 UA_ByteString *data, const size_t plainTextBlockSize) {
71283 if(data->length % plainTextBlockSize != 0)
71284 return UA_STATUSCODE_BADINTERNALERROR;
71285
71286 size_t max_blocks = data->length / plainTextBlockSize;
71287
71288
71289 UA_ByteString encrypted;
71290#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71291 UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, max_blocks * context->len);
71292#else
71293 size_t keylen = mbedtls_rsa_get_len(context);
71294 UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, max_blocks * keylen);
71295
71296#endif
71297
71298 if(retval != UA_STATUSCODE_GOOD)
71299 return retval;
71300
71301 size_t lenDataToEncrypt = data->length;
71302 size_t inOffset = 0;
71303 size_t offset = 0;
71304 const unsigned char *label = NULL;
71305 while(lenDataToEncrypt >= plainTextBlockSize) {
71306#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71307 int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random,
71308 drbgContext, MBEDTLS_RSA_PUBLIC,
71309 label, 0, plainTextBlockSize,
71310 data->data + inOffset, encrypted.data + offset);
71311#else
71312 int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random,
71313 drbgContext, label, 0, plainTextBlockSize,
71314 data->data + inOffset, encrypted.data + offset);
71315#endif
71316
71317 if(mbedErr) {
71318 UA_ByteString_clear(&encrypted);
71319 return UA_STATUSCODE_BADINTERNALERROR;
71320 }
71321
71322 inOffset += plainTextBlockSize;
71323#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71324 offset += context->len;
71325#else
71326 offset += keylen;
71327#endif
71328 lenDataToEncrypt -= plainTextBlockSize;
71329 }
71330
71331 memcpy(data->data, encrypted.data, offset);
71332 UA_ByteString_clear(&encrypted);
71333 return UA_STATUSCODE_GOOD;
71334}
71335
71336UA_StatusCode
71337mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey,
71338 mbedtls_ctr_drbg_context *drbgContext,
71339 UA_ByteString *data) {
71340 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey);
71341 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
71342#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71343 if(data->length % rsaContext->len != 0)
71344 return UA_STATUSCODE_BADINTERNALERROR;
71345#else
71346 size_t keylen = mbedtls_rsa_get_len(rsaContext);
71347 if(data->length % keylen != 0)
71348 return UA_STATUSCODE_BADINTERNALERROR;
71349#endif
71350
71351 size_t inOffset = 0;
71352 size_t outOffset = 0;
71353 size_t outLength = 0;
71354 unsigned char buf[512];
71355
71356 while(inOffset < data->length) {
71357#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71358 int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random,
71359 drbgContext, MBEDTLS_RSA_PRIVATE,
71360 NULL, 0, &outLength,
71361 data->data + inOffset,
71362 buf, 512);
71363#else
71364 int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random,
71365 drbgContext,
71366 NULL, 0, &outLength,
71367 data->data + inOffset,
71368 buf, 512);
71369#endif
71370
71371 if(mbedErr)
71372 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
71373
71374 memcpy(data->data + outOffset, buf, outLength);
71375#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71376 inOffset += rsaContext->len;
71377#else
71378 inOffset += keylen;
71379#endif
71380 outOffset += outLength;
71381 }
71382
71383 data->length = outOffset;
71384 return UA_STATUSCODE_GOOD;
71385}
71386
71387int
71388UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target, void *p_rng) {
71389 UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(key);
71390#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71391 int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0);
71392#else
71393 int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0, mbedtls_entropy_func, p_rng);
71394#endif
71395 UA_ByteString_clear(&data);
71396 return mbedErr;
71397}
71398
71399UA_StatusCode
71400UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData,
71401 UA_ByteString *target) {
71402 UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(certData);
71403
71404 mbedtls_x509_crt cert;
71405 mbedtls_x509_crt_init(&cert);
71406
71407 int mbedErr = mbedtls_x509_crt_parse(&cert, data.data, data.length);
71408
71409 UA_StatusCode result = UA_STATUSCODE_BADINVALIDARGUMENT;
71410
71411 if (!mbedErr) {
71412 UA_ByteString tmp;
71413 tmp.data = cert.raw.p;
71414 tmp.length = cert.raw.len;
71415
71416 result = UA_ByteString_copy(&tmp, target);
71417 } else {
71418 UA_ByteString_init(target);
71419 }
71420
71421 UA_ByteString_clear(&data);
71422 mbedtls_x509_crt_free(&cert);
71423 return result;
71424}
71425
71426// mbedTLS expects PEM data to be null terminated
71427// The data length parameter must include the null terminator
71428UA_ByteString
71429UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data) {
71430 UA_ByteString result;
71431 UA_ByteString_init(&result);
71432
71433 if (!data->length)
71434 return result;
71435
71436 if (data->length && data->data[0] == '-') {
71437 UA_ByteString_allocBuffer(&result, data->length + 1);
71438 memcpy(result.data, data->data, data->length);
71439 result.data[data->length] = '\0';
71440 } else {
71441 UA_ByteString_copy(data, &result);
71442 }
71443
71444 return result;
71445}
71446
71447#endif
71448
71449/**** amalgamated original file "/plugins/ua_log_stdout.c" ****/
71450
71451/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
71452 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
71453 *
71454 * Copyright 2016-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
71455 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
71456 */
71457
71458
71459#include <stdio.h>
71460
71461#if UA_MULTITHREADING >= 100
71462#include <pthread.h>
71463static pthread_mutex_t printf_mutex = PTHREAD_MUTEX_INITIALIZER;
71464#endif
71465
71466/* ANSI escape sequences for color output taken from here:
71467 * https://stackoverflow.com/questions/3219393/stdlib-and-colored-output-in-c*/
71468
71469#ifdef UA_ENABLE_LOG_COLORS
71470# define ANSI_COLOR_RED "\x1b[31m"
71471# define ANSI_COLOR_GREEN "\x1b[32m"
71472# define ANSI_COLOR_YELLOW "\x1b[33m"
71473# define ANSI_COLOR_BLUE "\x1b[34m"
71474# define ANSI_COLOR_MAGENTA "\x1b[35m"
71475# define ANSI_COLOR_CYAN "\x1b[36m"
71476# define ANSI_COLOR_RESET "\x1b[0m"
71477#else
71478# define ANSI_COLOR_RED ""
71479# define ANSI_COLOR_GREEN ""
71480# define ANSI_COLOR_YELLOW ""
71481# define ANSI_COLOR_BLUE ""
71482# define ANSI_COLOR_MAGENTA ""
71483# define ANSI_COLOR_CYAN ""
71484# define ANSI_COLOR_RESET ""
71485#endif
71486
71487const char *logLevelNames[6] = {"trace", "debug",
71488 ANSI_COLOR_GREEN "info",
71489 ANSI_COLOR_YELLOW "warn",
71490 ANSI_COLOR_RED "error",
71491 ANSI_COLOR_MAGENTA "fatal"};
71492const char *logCategoryNames[7] = {"network", "channel", "session", "server",
71493 "client", "userland", "securitypolicy"};
71494
71495#ifdef __clang__
71496__attribute__((__format__(__printf__, 4 , 0)))
71497#endif
71498void
71499UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category,
71500 const char *msg, va_list args) {
71501
71502 /* Assume that context is casted to UA_LogLevel */
71503 /* TODO we may later change this to a struct with bitfields to filter on category */
71504 if ( context != NULL && (UA_LogLevel)(uintptr_t)context > level )
71505 return;
71506
71507 UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
71508 UA_DateTimeStruct dts = UA_DateTime_toStruct(t: UA_DateTime_now() + tOffset);
71509
71510#if UA_MULTITHREADING >= 100
71511 pthread_mutex_lock(&printf_mutex);
71512#endif
71513
71514 printf(format: "[%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)] %s/%s" ANSI_COLOR_RESET "\t",
71515 dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec,
71516 (int)(tOffset / UA_DATETIME_SEC / 36), logLevelNames[level], logCategoryNames[category]);
71517 vprintf(format: msg, arg: args);
71518 printf(format: "\n");
71519 fflush(stdout);
71520
71521#if UA_MULTITHREADING >= 100
71522 pthread_mutex_unlock(&printf_mutex);
71523#endif
71524}
71525
71526void
71527UA_Log_Stdout_clear(void *logContext) {
71528
71529}
71530
71531const UA_Logger UA_Log_Stdout_ = {UA_Log_Stdout_log, NULL, UA_Log_Stdout_clear};
71532const UA_Logger *UA_Log_Stdout = &UA_Log_Stdout_;
71533
71534/* By default the client and server is configured with UA_Log_Stdout
71535 This constructs a logger with a configurable max log level */
71536
71537UA_Logger UA_Log_Stdout_withLevel(UA_LogLevel minlevel)
71538{
71539 UA_Logger logger = {UA_Log_Stdout_log, (void*)minlevel, UA_Log_Stdout_clear};
71540 return logger;
71541}
71542
71543/**** amalgamated original file "/plugins/ua_accesscontrol_default.c" ****/
71544
71545/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
71546 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
71547 *
71548 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
71549 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
71550 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
71551 */
71552
71553
71554/* Example access control management. Anonymous and username / password login.
71555 * The access rights are maximally permissive.
71556 *
71557 * FOR PRODUCTION USE, THIS EXAMPLE PLUGIN SHOULD BE REPLACED WITH LESS
71558 * PERMISSIVE ACCESS CONTROL.
71559 *
71560 * For TransferSubscriptions, we check whether the transfer happens between
71561 * Sessions for the same user. */
71562
71563typedef struct {
71564 UA_Boolean allowAnonymous;
71565 size_t usernamePasswordLoginSize;
71566 UA_UsernamePasswordLogin *usernamePasswordLogin;
71567 UA_CertificateVerification verifyX509;
71568} AccessControlContext;
71569
71570#define ANONYMOUS_POLICY "open62541-anonymous-policy"
71571#define CERTIFICATE_POLICY "open62541-certificate-policy"
71572#define USERNAME_POLICY "open62541-username-policy"
71573const UA_String anonymous_policy = UA_STRING_STATIC(ANONYMOUS_POLICY);
71574const UA_String certificate_policy = UA_STRING_STATIC(CERTIFICATE_POLICY);
71575const UA_String username_policy = UA_STRING_STATIC(USERNAME_POLICY);
71576
71577/************************/
71578/* Access Control Logic */
71579/************************/
71580
71581static UA_StatusCode
71582activateSession_default(UA_Server *server, UA_AccessControl *ac,
71583 const UA_EndpointDescription *endpointDescription,
71584 const UA_ByteString *secureChannelRemoteCertificate,
71585 const UA_NodeId *sessionId,
71586 const UA_ExtensionObject *userIdentityToken,
71587 void **sessionContext) {
71588 AccessControlContext *context = (AccessControlContext*)ac->context;
71589
71590 /* The empty token is interpreted as anonymous */
71591 if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
71592 if(!context->allowAnonymous)
71593 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71594
71595 /* No userdata atm */
71596 *sessionContext = NULL;
71597 return UA_STATUSCODE_GOOD;
71598 }
71599
71600 /* Could the token be decoded? */
71601 if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
71602 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71603
71604 /* Anonymous login */
71605 if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
71606 if(!context->allowAnonymous)
71607 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71608
71609 const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
71610 userIdentityToken->content.decoded.data;
71611
71612 /* Compatibility notice: Siemens OPC Scout v10 provides an empty
71613 * policyId. This is not compliant. For compatibility, assume that empty
71614 * policyId == ANONYMOUS_POLICY */
71615 if(token->policyId.data && !UA_String_equal(s1: &token->policyId, s2: &anonymous_policy))
71616 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71617
71618 /* No userdata atm */
71619 *sessionContext = NULL;
71620 return UA_STATUSCODE_GOOD;
71621 }
71622
71623 /* Username and password */
71624 if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
71625 const UA_UserNameIdentityToken *userToken =
71626 (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
71627
71628 if(!UA_String_equal(s1: &userToken->policyId, s2: &username_policy))
71629 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71630
71631 /* The userToken has been decrypted by the server before forwarding
71632 * it to the plugin. This information can be used here. */
71633 /* if(userToken->encryptionAlgorithm.length > 0) {} */
71634
71635 /* Empty username and password */
71636 if(userToken->userName.length == 0 && userToken->password.length == 0)
71637 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71638
71639 /* Try to match username/pw */
71640 UA_Boolean match = false;
71641 for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
71642 if(UA_String_equal(s1: &userToken->userName, s2: &context->usernamePasswordLogin[i].username) &&
71643 UA_String_equal(s1: &userToken->password, s2: &context->usernamePasswordLogin[i].password)) {
71644 match = true;
71645 break;
71646 }
71647 }
71648 if(!match)
71649 return UA_STATUSCODE_BADUSERACCESSDENIED;
71650
71651 /* For the CTT, recognize whether two sessions are */
71652 UA_ByteString *username = UA_ByteString_new();
71653 if(username)
71654 UA_ByteString_copy(src: &userToken->userName, dst: username);
71655 *sessionContext = username;
71656 return UA_STATUSCODE_GOOD;
71657 }
71658
71659 /* x509 certificate */
71660 if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
71661 const UA_X509IdentityToken *userToken = (UA_X509IdentityToken*)
71662 userIdentityToken->content.decoded.data;
71663
71664 if(!UA_String_equal(s1: &userToken->policyId, s2: &certificate_policy))
71665 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71666
71667 if(!context->verifyX509.verifyCertificate)
71668 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71669
71670 return context->verifyX509.
71671 verifyCertificate(context->verifyX509.context,
71672 &userToken->certificateData);
71673 }
71674
71675 /* Unsupported token type */
71676 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71677}
71678
71679static void
71680closeSession_default(UA_Server *server, UA_AccessControl *ac,
71681 const UA_NodeId *sessionId, void *sessionContext) {
71682 if(sessionContext)
71683 UA_ByteString_delete(p: (UA_ByteString*)sessionContext);
71684}
71685
71686static UA_UInt32
71687getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
71688 const UA_NodeId *sessionId, void *sessionContext,
71689 const UA_NodeId *nodeId, void *nodeContext) {
71690 return 0xFFFFFFFF;
71691}
71692
71693static UA_Byte
71694getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
71695 const UA_NodeId *sessionId, void *sessionContext,
71696 const UA_NodeId *nodeId, void *nodeContext) {
71697 return 0xFF;
71698}
71699
71700static UA_Boolean
71701getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
71702 const UA_NodeId *sessionId, void *sessionContext,
71703 const UA_NodeId *methodId, void *methodContext) {
71704 return true;
71705}
71706
71707static UA_Boolean
71708getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
71709 const UA_NodeId *sessionId, void *sessionContext,
71710 const UA_NodeId *methodId, void *methodContext,
71711 const UA_NodeId *objectId, void *objectContext) {
71712 return true;
71713}
71714
71715static UA_Boolean
71716allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
71717 const UA_NodeId *sessionId, void *sessionContext,
71718 const UA_AddNodesItem *item) {
71719 return true;
71720}
71721
71722static UA_Boolean
71723allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
71724 const UA_NodeId *sessionId, void *sessionContext,
71725 const UA_AddReferencesItem *item) {
71726 return true;
71727}
71728
71729static UA_Boolean
71730allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
71731 const UA_NodeId *sessionId, void *sessionContext,
71732 const UA_DeleteNodesItem *item) {
71733 return true;
71734}
71735
71736static UA_Boolean
71737allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
71738 const UA_NodeId *sessionId, void *sessionContext,
71739 const UA_DeleteReferencesItem *item) {
71740 return true;
71741}
71742
71743static UA_Boolean
71744allowBrowseNode_default(UA_Server *server, UA_AccessControl *ac,
71745 const UA_NodeId *sessionId, void *sessionContext,
71746 const UA_NodeId *nodeId, void *nodeContext) {
71747 return true;
71748}
71749
71750#ifdef UA_ENABLE_SUBSCRIPTIONS
71751static UA_Boolean
71752allowTransferSubscription_default(UA_Server *server, UA_AccessControl *ac,
71753 const UA_NodeId *oldSessionId, void *oldSessionContext,
71754 const UA_NodeId *newSessionId, void *newSessionContext) {
71755 if(oldSessionContext == newSessionContext)
71756 return true;
71757 if(oldSessionContext && newSessionContext)
71758 return UA_ByteString_equal(string1: (UA_ByteString*)oldSessionContext,
71759 string2: (UA_ByteString*)newSessionContext);
71760 return false;
71761}
71762#endif
71763
71764#ifdef UA_ENABLE_HISTORIZING
71765static UA_Boolean
71766allowHistoryUpdateUpdateData_default(UA_Server *server, UA_AccessControl *ac,
71767 const UA_NodeId *sessionId, void *sessionContext,
71768 const UA_NodeId *nodeId,
71769 UA_PerformUpdateType performInsertReplace,
71770 const UA_DataValue *value) {
71771 return true;
71772}
71773
71774static UA_Boolean
71775allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl *ac,
71776 const UA_NodeId *sessionId, void *sessionContext,
71777 const UA_NodeId *nodeId,
71778 UA_DateTime startTimestamp,
71779 UA_DateTime endTimestamp,
71780 bool isDeleteModified) {
71781 return true;
71782}
71783#endif
71784
71785/***************************************/
71786/* Create Delete Access Control Plugin */
71787/***************************************/
71788
71789static void clear_default(UA_AccessControl *ac) {
71790 UA_Array_delete(p: (void*)(uintptr_t)ac->userTokenPolicies,
71791 size: ac->userTokenPoliciesSize,
71792 type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
71793 ac->userTokenPolicies = NULL;
71794 ac->userTokenPoliciesSize = 0;
71795
71796 AccessControlContext *context = (AccessControlContext*)ac->context;
71797
71798 if (context) {
71799 for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
71800 UA_String_clear(p: &context->usernamePasswordLogin[i].username);
71801 UA_String_clear(p: &context->usernamePasswordLogin[i].password);
71802 }
71803 if(context->usernamePasswordLoginSize > 0)
71804 UA_free(ptr: context->usernamePasswordLogin);
71805
71806 if(context->verifyX509.clear)
71807 context->verifyX509.clear(&context->verifyX509);
71808
71809 UA_free(ptr: ac->context);
71810 ac->context = NULL;
71811 }
71812}
71813
71814UA_StatusCode
71815UA_AccessControl_default(UA_ServerConfig *config,
71816 UA_Boolean allowAnonymous,
71817 UA_CertificateVerification *verifyX509,
71818 const UA_ByteString *userTokenPolicyUri,
71819 size_t usernamePasswordLoginSize,
71820 const UA_UsernamePasswordLogin *usernamePasswordLogin) {
71821 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
71822 msg: "AccessControl: Unconfigured AccessControl. Users have all permissions.");
71823 UA_AccessControl *ac = &config->accessControl;
71824
71825 if(ac->clear)
71826 clear_default(ac);
71827
71828 ac->clear = clear_default;
71829 ac->activateSession = activateSession_default;
71830 ac->closeSession = closeSession_default;
71831 ac->getUserRightsMask = getUserRightsMask_default;
71832 ac->getUserAccessLevel = getUserAccessLevel_default;
71833 ac->getUserExecutable = getUserExecutable_default;
71834 ac->getUserExecutableOnObject = getUserExecutableOnObject_default;
71835 ac->allowAddNode = allowAddNode_default;
71836 ac->allowAddReference = allowAddReference_default;
71837 ac->allowBrowseNode = allowBrowseNode_default;
71838
71839#ifdef UA_ENABLE_SUBSCRIPTIONS
71840 ac->allowTransferSubscription = allowTransferSubscription_default;
71841#endif
71842
71843#ifdef UA_ENABLE_HISTORIZING
71844 ac->allowHistoryUpdateUpdateData = allowHistoryUpdateUpdateData_default;
71845 ac->allowHistoryUpdateDeleteRawModified = allowHistoryUpdateDeleteRawModified_default;
71846#endif
71847
71848 ac->allowDeleteNode = allowDeleteNode_default;
71849 ac->allowDeleteReference = allowDeleteReference_default;
71850
71851 AccessControlContext *context = (AccessControlContext*)
71852 UA_malloc(size: sizeof(AccessControlContext));
71853 if(!context)
71854 return UA_STATUSCODE_BADOUTOFMEMORY;
71855 memset(s: context, c: 0, n: sizeof(AccessControlContext));
71856 ac->context = context;
71857
71858 /* Allow anonymous? */
71859 context->allowAnonymous = allowAnonymous;
71860 if(allowAnonymous) {
71861 UA_LOG_INFO(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
71862 msg: "AccessControl: Anonymous login is enabled");
71863 }
71864
71865 /* Allow x509 certificates? Move the plugin over. */
71866 if(verifyX509) {
71867 context->verifyX509 = *verifyX509;
71868 memset(s: verifyX509, c: 0, n: sizeof(UA_CertificateVerification));
71869 } else {
71870 memset(s: &context->verifyX509, c: 0, n: sizeof(UA_CertificateVerification));
71871 UA_LOG_INFO(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
71872 msg: "AccessControl: x509 certificate user authentication is enabled");
71873 }
71874
71875 /* Copy username/password to the access control plugin */
71876 if(usernamePasswordLoginSize > 0) {
71877 context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
71878 UA_malloc(size: usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
71879 if(!context->usernamePasswordLogin)
71880 return UA_STATUSCODE_BADOUTOFMEMORY;
71881 context->usernamePasswordLoginSize = usernamePasswordLoginSize;
71882 for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
71883 UA_String_copy(src: &usernamePasswordLogin[i].username,
71884 dst: &context->usernamePasswordLogin[i].username);
71885 UA_String_copy(src: &usernamePasswordLogin[i].password,
71886 dst: &context->usernamePasswordLogin[i].password);
71887 }
71888 }
71889
71890 /* Set the allowed policies */
71891 size_t policies = 0;
71892 if(allowAnonymous)
71893 policies++;
71894 if(verifyX509)
71895 policies++;
71896 if(usernamePasswordLoginSize > 0)
71897 policies++;
71898 ac->userTokenPoliciesSize = 0;
71899 ac->userTokenPolicies = (UA_UserTokenPolicy *)
71900 UA_Array_new(size: policies, type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
71901 if(!ac->userTokenPolicies)
71902 return UA_STATUSCODE_BADOUTOFMEMORY;
71903 ac->userTokenPoliciesSize = policies;
71904
71905 policies = 0;
71906 if(allowAnonymous) {
71907 ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
71908 ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
71909 policies++;
71910 }
71911
71912 if(verifyX509) {
71913 ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_CERTIFICATE;
71914 ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(CERTIFICATE_POLICY);
71915#if UA_LOGLEVEL <= 400
71916 if(UA_ByteString_equal(string1: userTokenPolicyUri, string2: &UA_SECURITY_POLICY_NONE_URI)) {
71917 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
71918 msg: "x509 Certificate Authentication configured, "
71919 "but no encrypting SecurityPolicy. "
71920 "This can leak credentials on the network.");
71921 }
71922#endif
71923 UA_ByteString_copy(src: userTokenPolicyUri,
71924 dst: &ac->userTokenPolicies[policies].securityPolicyUri);
71925 policies++;
71926 }
71927
71928 if(usernamePasswordLoginSize > 0) {
71929 ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
71930 ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
71931#if UA_LOGLEVEL <= 400
71932 if(UA_ByteString_equal(string1: userTokenPolicyUri, string2: &UA_SECURITY_POLICY_NONE_URI)) {
71933 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
71934 msg: "Username/Password Authentication configured, "
71935 "but no encrypting SecurityPolicy. "
71936 "This can leak credentials on the network.");
71937 }
71938#endif
71939 UA_ByteString_copy(src: userTokenPolicyUri,
71940 dst: &ac->userTokenPolicies[policies].securityPolicyUri);
71941 }
71942 return UA_STATUSCODE_GOOD;
71943}
71944
71945
71946/**** amalgamated original file "/plugins/ua_nodestore_ziptree.c" ****/
71947
71948/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
71949 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
71950 *
71951 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
71952 * Copyright 2017 (c) Julian Grothoff
71953 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
71954 */
71955
71956
71957#ifndef container_of
71958#define container_of(ptr, type, member) \
71959 (type *)((uintptr_t)ptr - offsetof(type,member))
71960#endif
71961
71962struct NodeEntry;
71963typedef struct NodeEntry NodeEntry;
71964
71965struct NodeEntry {
71966 ZIP_ENTRY(NodeEntry) zipfields;
71967 UA_UInt32 nodeIdHash;
71968 UA_UInt16 refCount; /* How many consumers have a reference to the node? */
71969 UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
71970 NodeEntry *orig; /* If a copy is made to replace a node, track that we
71971 * replace only the node from which the copy was made.
71972 * Important for concurrent operations. */
71973 UA_NodeId nodeId; /* This is actually a UA_Node that also starts with a NodeId */
71974};
71975
71976/* Absolute ordering for NodeIds */
71977static enum ZIP_CMP
71978cmpNodeId(const void *a, const void *b) {
71979 const NodeEntry *aa = (const NodeEntry*)a;
71980 const NodeEntry *bb = (const NodeEntry*)b;
71981
71982 /* Compare hash */
71983 if(aa->nodeIdHash < bb->nodeIdHash)
71984 return ZIP_CMP_LESS;
71985 if(aa->nodeIdHash > bb->nodeIdHash)
71986 return ZIP_CMP_MORE;
71987
71988 /* Compore nodes in detail */
71989 return (enum ZIP_CMP)UA_NodeId_order(n1: &aa->nodeId, n2: &bb->nodeId);
71990}
71991
71992ZIP_HEAD(NodeTree, NodeEntry);
71993typedef struct NodeTree NodeTree;
71994
71995typedef struct {
71996 NodeTree root;
71997
71998 /* Maps ReferenceTypeIndex to the NodeId of the ReferenceType */
71999 UA_NodeId referenceTypeIds[UA_REFERENCETYPESET_MAX];
72000 UA_Byte referenceTypeCounter;
72001} ZipContext;
72002
72003ZIP_FUNCTIONS(NodeTree, NodeEntry, zipfields, NodeEntry, zipfields, cmpNodeId)
72004
72005static NodeEntry *
72006newEntry(UA_NodeClass nodeClass) {
72007 size_t size = sizeof(NodeEntry) - sizeof(UA_NodeId);
72008 switch(nodeClass) {
72009 case UA_NODECLASS_OBJECT:
72010 size += sizeof(UA_ObjectNode);
72011 break;
72012 case UA_NODECLASS_VARIABLE:
72013 size += sizeof(UA_VariableNode);
72014 break;
72015 case UA_NODECLASS_METHOD:
72016 size += sizeof(UA_MethodNode);
72017 break;
72018 case UA_NODECLASS_OBJECTTYPE:
72019 size += sizeof(UA_ObjectTypeNode);
72020 break;
72021 case UA_NODECLASS_VARIABLETYPE:
72022 size += sizeof(UA_VariableTypeNode);
72023 break;
72024 case UA_NODECLASS_REFERENCETYPE:
72025 size += sizeof(UA_ReferenceTypeNode);
72026 break;
72027 case UA_NODECLASS_DATATYPE:
72028 size += sizeof(UA_DataTypeNode);
72029 break;
72030 case UA_NODECLASS_VIEW:
72031 size += sizeof(UA_ViewNode);
72032 break;
72033 default:
72034 return NULL;
72035 }
72036 NodeEntry *entry = (NodeEntry*)UA_calloc(nmemb: 1, size: size);
72037 if(!entry)
72038 return NULL;
72039 UA_Node *node = (UA_Node*)&entry->nodeId;
72040 node->head.nodeClass = nodeClass;
72041 return entry;
72042}
72043
72044static void
72045deleteEntry(NodeEntry *entry) {
72046 UA_Node_clear(node: (UA_Node*)&entry->nodeId);
72047 UA_free(ptr: entry);
72048}
72049
72050static void
72051cleanupEntry(NodeEntry *entry) {
72052 if(entry->refCount > 0)
72053 return;
72054 if(entry->deleted) {
72055 deleteEntry(entry);
72056 return;
72057 }
72058 UA_NodeHead *head = (UA_NodeHead*)&entry->nodeId;
72059 for(size_t i = 0; i < head->referencesSize; i++) {
72060 UA_NodeReferenceKind *rk = &head->references[i];
72061 if(rk->targetsSize > 16 && !rk->hasRefTree)
72062 UA_NodeReferenceKind_switch(rk);
72063 }
72064}
72065
72066/***********************/
72067/* Interface functions */
72068/***********************/
72069
72070/* Not yet inserted into the ZipContext */
72071static UA_Node *
72072zipNsNewNode(void *nsCtx, UA_NodeClass nodeClass) {
72073 NodeEntry *entry = newEntry(nodeClass);
72074 if(!entry)
72075 return NULL;
72076 return (UA_Node*)&entry->nodeId;
72077}
72078
72079/* Not yet inserted into the ZipContext */
72080static void
72081zipNsDeleteNode(void *nsCtx, UA_Node *node) {
72082 deleteEntry(container_of(node, NodeEntry, nodeId));
72083}
72084
72085static const UA_Node *
72086zipNsGetNode(void *nsCtx, const UA_NodeId *nodeId) {
72087 ZipContext *ns = (ZipContext*)nsCtx;
72088 NodeEntry dummy;
72089 dummy.nodeIdHash = UA_NodeId_hash(n: nodeId);
72090 dummy.nodeId = *nodeId;
72091 NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
72092 if(!entry)
72093 return NULL;
72094 ++entry->refCount;
72095 return (const UA_Node*)&entry->nodeId;
72096}
72097
72098static void
72099zipNsReleaseNode(void *nsCtx, const UA_Node *node) {
72100 if(!node)
72101 return;
72102 NodeEntry *entry = container_of(node, NodeEntry, nodeId);
72103 UA_assert(entry->refCount > 0);
72104 --entry->refCount;
72105 cleanupEntry(entry);
72106}
72107
72108static UA_StatusCode
72109zipNsGetNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
72110 UA_Node **outNode) {
72111 /* Find the node */
72112 const UA_Node *node = zipNsGetNode(nsCtx, nodeId);
72113 if(!node)
72114 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72115
72116 /* Create the new entry */
72117 NodeEntry *ne = newEntry(nodeClass: node->head.nodeClass);
72118 if(!ne) {
72119 zipNsReleaseNode(nsCtx, node);
72120 return UA_STATUSCODE_BADOUTOFMEMORY;
72121 }
72122
72123 /* Copy the node content */
72124 UA_Node *nnode = (UA_Node*)&ne->nodeId;
72125 UA_StatusCode retval = UA_Node_copy(src: node, dst: nnode);
72126 zipNsReleaseNode(nsCtx, node);
72127 if(retval != UA_STATUSCODE_GOOD) {
72128 deleteEntry(entry: ne);
72129 return retval;
72130 }
72131
72132 ne->orig = container_of(node, NodeEntry, nodeId);
72133 *outNode = nnode;
72134 return UA_STATUSCODE_GOOD;
72135}
72136
72137static UA_StatusCode
72138zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
72139 NodeEntry *entry = container_of(node, NodeEntry, nodeId);
72140 ZipContext *ns = (ZipContext*)nsCtx;
72141
72142 /* Ensure that the NodeId is unique */
72143 NodeEntry dummy;
72144 memset(s: &dummy, c: 0, n: sizeof(NodeEntry));
72145 dummy.nodeId = node->head.nodeId;
72146 if(node->head.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
72147 node->head.nodeId.identifier.numeric == 0) {
72148 do { /* Create a random nodeid until we find an unoccupied id */
72149 UA_UInt32 numId = UA_UInt32_random();
72150#if SIZE_MAX <= UA_UINT32_MAX
72151 /* The compressed "immediate" representation of nodes does not
72152 * support the full range on 32bit systems. Generate smaller
72153 * identifiers as they can be stored more compactly. */
72154 if(numId >= (0x01 << 24))
72155 numId = numId % (0x01 << 24);
72156#endif
72157 node->head.nodeId.identifier.numeric = numId;
72158 dummy.nodeId.identifier.numeric = numId;
72159 dummy.nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId);
72160 } while(ZIP_FIND(NodeTree, &ns->root, &dummy));
72161 } else {
72162 dummy.nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId);
72163 if(ZIP_FIND(NodeTree, &ns->root, &dummy)) { /* The nodeid exists */
72164 deleteEntry(entry);
72165 return UA_STATUSCODE_BADNODEIDEXISTS;
72166 }
72167 }
72168
72169 /* Copy the NodeId */
72170 if(addedNodeId) {
72171 UA_StatusCode retval = UA_NodeId_copy(src: &node->head.nodeId, dst: addedNodeId);
72172 if(retval != UA_STATUSCODE_GOOD) {
72173 deleteEntry(entry);
72174 return retval;
72175 }
72176 }
72177
72178 /* For new ReferencetypeNodes add to the index map */
72179 if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
72180 UA_ReferenceTypeNode *refNode = &node->referenceTypeNode;
72181 if(ns->referenceTypeCounter >= UA_REFERENCETYPESET_MAX) {
72182 deleteEntry(entry);
72183 return UA_STATUSCODE_BADINTERNALERROR;
72184 }
72185
72186 UA_StatusCode retval =
72187 UA_NodeId_copy(src: &node->head.nodeId, dst: &ns->referenceTypeIds[ns->referenceTypeCounter]);
72188 if(retval != UA_STATUSCODE_GOOD) {
72189 deleteEntry(entry);
72190 return UA_STATUSCODE_BADINTERNALERROR;
72191 }
72192
72193 /* Assign the ReferenceTypeIndex to the new ReferenceTypeNode */
72194 refNode->referenceTypeIndex = ns->referenceTypeCounter;
72195 refNode->subTypes = UA_REFTYPESET(index: ns->referenceTypeCounter);
72196
72197 ns->referenceTypeCounter++;
72198 }
72199
72200 /* Insert the node */
72201 entry->nodeIdHash = dummy.nodeIdHash;
72202 ZIP_INSERT(NodeTree, &ns->root, entry, UA_UInt32_random());
72203 return UA_STATUSCODE_GOOD;
72204}
72205
72206static UA_StatusCode
72207zipNsReplaceNode(void *nsCtx, UA_Node *node) {
72208 /* Find the node */
72209 const UA_Node *oldNode = zipNsGetNode(nsCtx, nodeId: &node->head.nodeId);
72210 if(!oldNode) {
72211 deleteEntry(container_of(node, NodeEntry, nodeId));
72212 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72213 }
72214
72215 /* Test if the copy is current */
72216 NodeEntry *entry = container_of(node, NodeEntry, nodeId);
72217 NodeEntry *oldEntry = container_of(oldNode, NodeEntry, nodeId);
72218 if(oldEntry != entry->orig) {
72219 /* The node was already updated since the copy was made */
72220 deleteEntry(entry);
72221 zipNsReleaseNode(nsCtx, node: oldNode);
72222 return UA_STATUSCODE_BADINTERNALERROR;
72223 }
72224
72225 /* Replace */
72226 ZipContext *ns = (ZipContext*)nsCtx;
72227 ZIP_REMOVE(NodeTree, &ns->root, oldEntry);
72228 entry->nodeIdHash = oldEntry->nodeIdHash;
72229 ZIP_INSERT(NodeTree, &ns->root, entry, ZIP_RANK(entry, zipfields));
72230 oldEntry->deleted = true;
72231
72232 zipNsReleaseNode(nsCtx, node: oldNode);
72233 return UA_STATUSCODE_GOOD;
72234}
72235
72236static UA_StatusCode
72237zipNsRemoveNode(void *nsCtx, const UA_NodeId *nodeId) {
72238 ZipContext *ns = (ZipContext*)nsCtx;
72239 NodeEntry dummy;
72240 dummy.nodeIdHash = UA_NodeId_hash(n: nodeId);
72241 dummy.nodeId = *nodeId;
72242 NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
72243 if(!entry)
72244 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72245 ZIP_REMOVE(NodeTree, &ns->root, entry);
72246 entry->deleted = true;
72247 cleanupEntry(entry);
72248 return UA_STATUSCODE_GOOD;
72249}
72250
72251static const UA_NodeId *
72252zipNsGetReferenceTypeId(void *nsCtx, UA_Byte refTypeIndex) {
72253 ZipContext *ns = (ZipContext*)nsCtx;
72254 if(refTypeIndex >= ns->referenceTypeCounter)
72255 return NULL;
72256 return &ns->referenceTypeIds[refTypeIndex];
72257}
72258
72259struct VisitorData {
72260 UA_NodestoreVisitor visitor;
72261 void *visitorContext;
72262};
72263
72264static void
72265nodeVisitor(NodeEntry *entry, void *data) {
72266 struct VisitorData *d = (struct VisitorData*)data;
72267 d->visitor(d->visitorContext, (UA_Node*)&entry->nodeId);
72268}
72269
72270static void
72271zipNsIterate(void *nsCtx, UA_NodestoreVisitor visitor,
72272 void *visitorCtx) {
72273 struct VisitorData d;
72274 d.visitor = visitor;
72275 d.visitorContext = visitorCtx;
72276 ZipContext *ns = (ZipContext*)nsCtx;
72277 ZIP_ITER(NodeTree, &ns->root, nodeVisitor, &d);
72278}
72279
72280static void
72281deleteNodeVisitor(NodeEntry *entry, void *data) {
72282 deleteEntry(entry);
72283}
72284
72285/***********************/
72286/* Nodestore Lifecycle */
72287/***********************/
72288
72289static void
72290zipNsClear(void *nsCtx) {
72291 if (!nsCtx)
72292 return;
72293 ZipContext *ns = (ZipContext*)nsCtx;
72294 ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL);
72295
72296 /* Clean up the ReferenceTypes index array */
72297 for(size_t i = 0; i < ns->referenceTypeCounter; i++)
72298 UA_NodeId_clear(p: &ns->referenceTypeIds[i]);
72299
72300 UA_free(ptr: ns);
72301}
72302
72303UA_StatusCode
72304UA_Nodestore_ZipTree(UA_Nodestore *ns) {
72305 /* Allocate and initialize the context */
72306 ZipContext *ctx = (ZipContext*)UA_malloc(size: sizeof(ZipContext));
72307 if(!ctx)
72308 return UA_STATUSCODE_BADOUTOFMEMORY;
72309
72310 ZIP_INIT(&ctx->root);
72311 ctx->referenceTypeCounter = 0;
72312
72313 /* Populate the nodestore */
72314 ns->context = (void*)ctx;
72315 ns->clear = zipNsClear;
72316 ns->newNode = zipNsNewNode;
72317 ns->deleteNode = zipNsDeleteNode;
72318 ns->getNode = zipNsGetNode;
72319 ns->releaseNode = zipNsReleaseNode;
72320 ns->getNodeCopy = zipNsGetNodeCopy;
72321 ns->insertNode = zipNsInsertNode;
72322 ns->replaceNode = zipNsReplaceNode;
72323 ns->removeNode = zipNsRemoveNode;
72324 ns->getReferenceTypeId = zipNsGetReferenceTypeId;
72325 ns->iterate = zipNsIterate;
72326
72327 return UA_STATUSCODE_GOOD;
72328}
72329
72330/**** amalgamated original file "/plugins/ua_nodestore_hashmap.c" ****/
72331
72332/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
72333 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
72334 *
72335 * Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
72336 * Copyright 2017 (c) Julian Grothoff
72337 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
72338 */
72339
72340
72341#ifndef container_of
72342#define container_of(ptr, type, member) \
72343 (type *)((uintptr_t)ptr - offsetof(type,member))
72344#endif
72345
72346/* The default Nodestore is simply a hash-map from NodeIds to Nodes. To find an
72347 * entry, iterate over candidate positions according to the NodeId hash.
72348 *
72349 * - Tombstone or non-matching NodeId: continue searching
72350 * - Matching NodeId: Return the entry
72351 * - NULL: Abort the search */
72352
72353typedef struct UA_NodeMapEntry {
72354 struct UA_NodeMapEntry *orig; /* the version this is a copy from (or NULL) */
72355 UA_UInt16 refCount; /* How many consumers have a reference to the node? */
72356 UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
72357 UA_Node node;
72358} UA_NodeMapEntry;
72359
72360#define UA_NODEMAP_MINSIZE 64
72361#define UA_NODEMAP_TOMBSTONE ((UA_NodeMapEntry*)0x01)
72362
72363typedef struct {
72364 UA_NodeMapEntry *entry;
72365 UA_UInt32 nodeIdHash;
72366} UA_NodeMapSlot;
72367
72368typedef struct {
72369 UA_NodeMapSlot *slots;
72370 UA_UInt32 size;
72371 UA_UInt32 count;
72372 UA_UInt32 sizePrimeIndex;
72373
72374 /* Maps ReferenceTypeIndex to the NodeId of the ReferenceType */
72375 UA_NodeId referenceTypeIds[UA_REFERENCETYPESET_MAX];
72376 UA_Byte referenceTypeCounter;
72377} UA_NodeMap;
72378
72379/*********************/
72380/* HashMap Utilities */
72381/*********************/
72382
72383/* The size of the hash-map is always a prime number. They are chosen to be
72384 * close to the next power of 2. So the size ca. doubles with each prime. */
72385static UA_UInt32 const primes[] = {
72386 7, 13, 31, 61, 127, 251,
72387 509, 1021, 2039, 4093, 8191, 16381,
72388 32749, 65521, 131071, 262139, 524287, 1048573,
72389 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
72390 134217689, 268435399, 536870909, 1073741789, 2147483647, 4294967291
72391};
72392
72393static UA_UInt32 mod(UA_UInt32 h, UA_UInt32 size) { return h % size; }
72394static UA_UInt32 mod2(UA_UInt32 h, UA_UInt32 size) { return 1 + (h % (size - 2)); }
72395
72396static UA_UInt16
72397higher_prime_index(UA_UInt32 n) {
72398 UA_UInt16 low = 0;
72399 UA_UInt16 high = (UA_UInt16)(sizeof(primes) / sizeof(UA_UInt32));
72400 while(low != high) {
72401 UA_UInt16 mid = (UA_UInt16)(low + ((high - low) / 2));
72402 if(n > primes[mid])
72403 low = (UA_UInt16)(mid + 1);
72404 else
72405 high = mid;
72406 }
72407 return low;
72408}
72409
72410/* Returns an empty slot or null if the nodeid exists or if no empty slot is found. */
72411static UA_NodeMapSlot *
72412findFreeSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
72413 UA_UInt32 h = UA_NodeId_hash(n: nodeid);
72414 UA_UInt32 size = ns->size;
72415 UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
72416 UA_UInt32 startIdx = (UA_UInt32)idx;
72417 UA_UInt32 hash2 = mod2(h, size);
72418
72419 UA_NodeMapSlot *candidate = NULL;
72420 do {
72421 UA_NodeMapSlot *slot = &ns->slots[(UA_UInt32)idx];
72422
72423 if(slot->entry > UA_NODEMAP_TOMBSTONE) {
72424 /* A Node with the NodeId does already exist */
72425 if(slot->nodeIdHash == h &&
72426 UA_NodeId_equal(n1: &slot->entry->node.head.nodeId, n2: nodeid))
72427 return NULL;
72428 } else {
72429 /* Found a candidate node */
72430 if(!candidate)
72431 candidate = slot;
72432 /* No matching node can come afterwards */
72433 if(slot->entry == NULL)
72434 return candidate;
72435 }
72436
72437 idx += hash2;
72438 if(idx >= size)
72439 idx -= size;
72440 } while((UA_UInt32)idx != startIdx);
72441
72442 return candidate;
72443}
72444
72445/* The occupancy of the table after the call will be about 50% */
72446static UA_StatusCode
72447expand(UA_NodeMap *ns) {
72448 UA_UInt32 osize = ns->size;
72449 UA_UInt32 count = ns->count;
72450 /* Resize only when table after removal of unused elements is either too
72451 full or too empty */
72452 if(count * 2 < osize && (count * 8 > osize || osize <= UA_NODEMAP_MINSIZE))
72453 return UA_STATUSCODE_GOOD;
72454
72455 UA_NodeMapSlot *oslots = ns->slots;
72456 UA_UInt32 nindex = higher_prime_index(n: count * 2);
72457 UA_UInt32 nsize = primes[nindex];
72458 UA_NodeMapSlot *nslots= (UA_NodeMapSlot*)UA_calloc(nmemb: nsize, size: sizeof(UA_NodeMapSlot));
72459 if(!nslots)
72460 return UA_STATUSCODE_BADOUTOFMEMORY;
72461
72462 ns->slots = nslots;
72463 ns->size = nsize;
72464 ns->sizePrimeIndex = nindex;
72465
72466 /* recompute the position of every entry and insert the pointer */
72467 for(size_t i = 0, j = 0; i < osize && j < count; ++i) {
72468 if(oslots[i].entry <= UA_NODEMAP_TOMBSTONE)
72469 continue;
72470 UA_NodeMapSlot *s = findFreeSlot(ns, nodeid: &oslots[i].entry->node.head.nodeId);
72471 UA_assert(s);
72472 *s = oslots[i];
72473 ++j;
72474 }
72475
72476 UA_free(ptr: oslots);
72477 return UA_STATUSCODE_GOOD;
72478}
72479
72480static UA_NodeMapEntry *
72481createEntry(UA_NodeClass nodeClass) {
72482 size_t size = sizeof(UA_NodeMapEntry) - sizeof(UA_Node);
72483 switch(nodeClass) {
72484 case UA_NODECLASS_OBJECT:
72485 size += sizeof(UA_ObjectNode);
72486 break;
72487 case UA_NODECLASS_VARIABLE:
72488 size += sizeof(UA_VariableNode);
72489 break;
72490 case UA_NODECLASS_METHOD:
72491 size += sizeof(UA_MethodNode);
72492 break;
72493 case UA_NODECLASS_OBJECTTYPE:
72494 size += sizeof(UA_ObjectTypeNode);
72495 break;
72496 case UA_NODECLASS_VARIABLETYPE:
72497 size += sizeof(UA_VariableTypeNode);
72498 break;
72499 case UA_NODECLASS_REFERENCETYPE:
72500 size += sizeof(UA_ReferenceTypeNode);
72501 break;
72502 case UA_NODECLASS_DATATYPE:
72503 size += sizeof(UA_DataTypeNode);
72504 break;
72505 case UA_NODECLASS_VIEW:
72506 size += sizeof(UA_ViewNode);
72507 break;
72508 default:
72509 return NULL;
72510 }
72511 UA_NodeMapEntry *entry = (UA_NodeMapEntry*)UA_calloc(nmemb: 1, size: size);
72512 if(!entry)
72513 return NULL;
72514 entry->node.head.nodeClass = nodeClass;
72515 return entry;
72516}
72517
72518static void
72519deleteNodeMapEntry(UA_NodeMapEntry *entry) {
72520 UA_Node_clear(node: &entry->node);
72521 UA_free(ptr: entry);
72522}
72523
72524static void
72525cleanupNodeMapEntry(UA_NodeMapEntry *entry) {
72526 if(entry->refCount > 0)
72527 return;
72528 if(entry->deleted) {
72529 deleteNodeMapEntry(entry);
72530 return;
72531 }
72532 for(size_t i = 0; i < entry->node.head.referencesSize; i++) {
72533 UA_NodeReferenceKind *rk = &entry->node.head.references[i];
72534 if(rk->targetsSize > 16 && !rk->hasRefTree)
72535 UA_NodeReferenceKind_switch(rk);
72536 }
72537}
72538
72539static UA_NodeMapSlot *
72540findOccupiedSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
72541 UA_UInt32 h = UA_NodeId_hash(n: nodeid);
72542 UA_UInt32 size = ns->size;
72543 UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
72544 UA_UInt32 hash2 = mod2(h, size);
72545 UA_UInt32 startIdx = (UA_UInt32)idx;
72546
72547 do {
72548 UA_NodeMapSlot *slot= &ns->slots[(UA_UInt32)idx];
72549 if(slot->entry > UA_NODEMAP_TOMBSTONE) {
72550 if(slot->nodeIdHash == h &&
72551 UA_NodeId_equal(n1: &slot->entry->node.head.nodeId, n2: nodeid))
72552 return slot;
72553 } else {
72554 if(slot->entry == NULL)
72555 return NULL; /* No further entry possible */
72556 }
72557
72558 idx += hash2;
72559 if(idx >= size)
72560 idx -= size;
72561 } while((UA_UInt32)idx != startIdx);
72562
72563 return NULL;
72564}
72565
72566/***********************/
72567/* Interface functions */
72568/***********************/
72569
72570static UA_Node *
72571UA_NodeMap_newNode(void *context, UA_NodeClass nodeClass) {
72572 UA_NodeMapEntry *entry = createEntry(nodeClass);
72573 if(!entry)
72574 return NULL;
72575 return &entry->node;
72576}
72577
72578static void
72579UA_NodeMap_deleteNode(void *context, UA_Node *node) {
72580 UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
72581 UA_assert(&entry->node == node);
72582 deleteNodeMapEntry(entry);
72583}
72584
72585static const UA_Node *
72586UA_NodeMap_getNode(void *context, const UA_NodeId *nodeid) {
72587 UA_NodeMap *ns = (UA_NodeMap*)context;
72588 UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
72589 if(!slot)
72590 return NULL;
72591 ++slot->entry->refCount;
72592 return &slot->entry->node;
72593}
72594
72595static void
72596UA_NodeMap_releaseNode(void *context, const UA_Node *node) {
72597 if (!node)
72598 return;
72599 UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
72600 UA_assert(&entry->node == node);
72601 UA_assert(entry->refCount > 0);
72602 --entry->refCount;
72603 cleanupNodeMapEntry(entry);
72604}
72605
72606static UA_StatusCode
72607UA_NodeMap_getNodeCopy(void *context, const UA_NodeId *nodeid,
72608 UA_Node **outNode) {
72609 UA_NodeMap *ns = (UA_NodeMap*)context;
72610 UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
72611 if(!slot)
72612 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72613 UA_NodeMapEntry *entry = slot->entry;
72614 UA_NodeMapEntry *newItem = createEntry(nodeClass: entry->node.head.nodeClass);
72615 if(!newItem)
72616 return UA_STATUSCODE_BADOUTOFMEMORY;
72617 UA_StatusCode retval = UA_Node_copy(src: &entry->node, dst: &newItem->node);
72618 if(retval == UA_STATUSCODE_GOOD) {
72619 newItem->orig = entry; /* Store the pointer to the original */
72620 *outNode = &newItem->node;
72621 } else {
72622 deleteNodeMapEntry(entry: newItem);
72623 }
72624 return retval;
72625}
72626
72627static UA_StatusCode
72628UA_NodeMap_removeNode(void *context, const UA_NodeId *nodeid) {
72629 UA_NodeMap *ns = (UA_NodeMap*)context;
72630 UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
72631 if(!slot)
72632 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72633
72634 UA_NodeMapEntry *entry = slot->entry;
72635 slot->entry = UA_NODEMAP_TOMBSTONE;
72636 UA_atomic_sync(); /* Set the tombstone before cleaning up. E.g. if the
72637 * nodestore is accessed from an interrupt. */
72638 entry->deleted = true;
72639 cleanupNodeMapEntry(entry);
72640 --ns->count;
72641 /* Downsize the hashmap if it is very empty */
72642 if(ns->count * 8 < ns->size && ns->size > UA_NODEMAP_MINSIZE)
72643 expand(ns); /* Can fail. Just continue with the bigger hashmap. */
72644 return UA_STATUSCODE_GOOD;
72645}
72646
72647/*
72648 * If this function fails in any way, the node parameter is deleted here,
72649 * so the caller function does not need to take care of it anymore
72650 */
72651static UA_StatusCode
72652UA_NodeMap_insertNode(void *context, UA_Node *node,
72653 UA_NodeId *addedNodeId) {
72654 UA_NodeMap *ns = (UA_NodeMap*)context;
72655 if(ns->size * 3 <= ns->count * 4) {
72656 if(expand(ns) != UA_STATUSCODE_GOOD){
72657 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72658 return UA_STATUSCODE_BADINTERNALERROR;
72659 }
72660 }
72661
72662 UA_NodeMapSlot *slot;
72663 if(node->head.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
72664 node->head.nodeId.identifier.numeric == 0) {
72665 /* Create a random nodeid: Start at least with 50,000 to make sure we
72666 * don not conflict with nodes from the spec. If we find a conflict, we
72667 * just try another identifier until we have tried all possible
72668 * identifiers. Since the size is prime and we don't change the increase
72669 * val, we will reach the starting id again. E.g. adding a nodeset will
72670 * create children while there are still other nodes which need to be
72671 * created. Thus the node ids may collide. */
72672 UA_UInt32 size = ns->size;
72673 UA_UInt64 identifier = mod(h: 50000 + size+1, UA_UINT32_MAX); /* Use 64bit to
72674 * avoid overflow */
72675 UA_UInt32 increase = mod2(h: ns->count+1, size);
72676 UA_UInt32 startId = (UA_UInt32)identifier; /* mod ensures us that the id
72677 * is a valid 32 bit integer */
72678
72679 do {
72680 node->head.nodeId.identifier.numeric = (UA_UInt32)identifier;
72681 slot = findFreeSlot(ns, nodeid: &node->head.nodeId);
72682 if(slot)
72683 break;
72684 identifier += increase;
72685 if(identifier >= size)
72686 identifier -= size;
72687#if SIZE_MAX <= UA_UINT32_MAX
72688 /* The compressed "immediate" representation of nodes does not
72689 * support the full range on 32bit systems. Generate smaller
72690 * identifiers as they can be stored more compactly. */
72691 if(identifier >= (0x01 << 24))
72692 identifier = identifier % (0x01 << 24);
72693#endif
72694 } while((UA_UInt32)identifier != startId);
72695 } else {
72696 slot = findFreeSlot(ns, nodeid: &node->head.nodeId);
72697 }
72698
72699 if(!slot) {
72700 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72701 return UA_STATUSCODE_BADNODEIDEXISTS;
72702 }
72703
72704 /* Copy the NodeId */
72705 UA_StatusCode retval = UA_STATUSCODE_GOOD;
72706 if(addedNodeId) {
72707 retval = UA_NodeId_copy(src: &node->head.nodeId, dst: addedNodeId);
72708 if(retval != UA_STATUSCODE_GOOD) {
72709 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72710 return retval;
72711 }
72712 }
72713
72714 /* For new ReferencetypeNodes add to the index map */
72715 if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
72716 UA_ReferenceTypeNode *refNode = &node->referenceTypeNode;
72717 if(ns->referenceTypeCounter >= UA_REFERENCETYPESET_MAX) {
72718 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72719 return UA_STATUSCODE_BADINTERNALERROR;
72720 }
72721
72722 retval = UA_NodeId_copy(src: &node->head.nodeId, dst: &ns->referenceTypeIds[ns->referenceTypeCounter]);
72723 if(retval != UA_STATUSCODE_GOOD) {
72724 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72725 return UA_STATUSCODE_BADINTERNALERROR;
72726 }
72727
72728 /* Assign the ReferenceTypeIndex to the new ReferenceTypeNode */
72729 refNode->referenceTypeIndex = ns->referenceTypeCounter;
72730 refNode->subTypes = UA_REFTYPESET(index: ns->referenceTypeCounter);
72731
72732 ns->referenceTypeCounter++;
72733 }
72734
72735 /* Insert the node */
72736 UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
72737 slot->nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId);
72738 UA_atomic_sync(); /* Set the hash first */
72739 slot->entry = newEntry;
72740 ++ns->count;
72741 return retval;
72742}
72743
72744static UA_StatusCode
72745UA_NodeMap_replaceNode(void *context, UA_Node *node) {
72746 UA_NodeMap *ns = (UA_NodeMap*)context;
72747 UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
72748
72749 /* Find the node */
72750 UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid: &node->head.nodeId);
72751 if(!slot) {
72752 deleteNodeMapEntry(entry: newEntry);
72753 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72754 }
72755
72756 /* The node was already updated since the copy was made? */
72757 UA_NodeMapEntry *oldEntry = slot->entry;
72758 if(oldEntry != newEntry->orig) {
72759 deleteNodeMapEntry(entry: newEntry);
72760 return UA_STATUSCODE_BADINTERNALERROR;
72761 }
72762
72763 /* Replace the entry */
72764 slot->entry = newEntry;
72765 UA_atomic_sync();
72766 oldEntry->deleted = true;
72767 cleanupNodeMapEntry(entry: oldEntry);
72768 return UA_STATUSCODE_GOOD;
72769}
72770
72771static const UA_NodeId *
72772UA_NodeMap_getReferenceTypeId(void *nsCtx, UA_Byte refTypeIndex) {
72773 UA_NodeMap *ns = (UA_NodeMap*)nsCtx;
72774 if(refTypeIndex >= ns->referenceTypeCounter)
72775 return NULL;
72776 return &ns->referenceTypeIds[refTypeIndex];
72777}
72778
72779static void
72780UA_NodeMap_iterate(void *context, UA_NodestoreVisitor visitor,
72781 void *visitorContext) {
72782 UA_NodeMap *ns = (UA_NodeMap*)context;
72783 for(UA_UInt32 i = 0; i < ns->size; ++i) {
72784 UA_NodeMapSlot *slot = &ns->slots[i];
72785 if(slot->entry > UA_NODEMAP_TOMBSTONE) {
72786 /* The visitor can delete the node. So refcount here. */
72787 slot->entry->refCount++;
72788 visitor(visitorContext, &slot->entry->node);
72789 slot->entry->refCount--;
72790 cleanupNodeMapEntry(entry: slot->entry);
72791 }
72792 }
72793}
72794
72795static void
72796UA_NodeMap_delete(void *context) {
72797 /* Already cleaned up? */
72798 if(!context)
72799 return;
72800
72801 UA_NodeMap *ns = (UA_NodeMap*)context;
72802 UA_UInt32 size = ns->size;
72803 UA_NodeMapSlot *slots = ns->slots;
72804 for(UA_UInt32 i = 0; i < size; ++i) {
72805 if(slots[i].entry > UA_NODEMAP_TOMBSTONE) {
72806 /* On debugging builds, check that all nodes were release */
72807 UA_assert(slots[i].entry->refCount == 0);
72808 /* Delete the node */
72809 deleteNodeMapEntry(entry: slots[i].entry);
72810 }
72811 }
72812 UA_free(ptr: ns->slots);
72813
72814 /* Clean up the ReferenceTypes index array */
72815 for(size_t i = 0; i < ns->referenceTypeCounter; i++)
72816 UA_NodeId_clear(p: &ns->referenceTypeIds[i]);
72817
72818 UA_free(ptr: ns);
72819}
72820
72821UA_StatusCode
72822UA_Nodestore_HashMap(UA_Nodestore *ns) {
72823 /* Allocate and initialize the nodemap */
72824 UA_NodeMap *nodemap = (UA_NodeMap*)UA_malloc(size: sizeof(UA_NodeMap));
72825 if(!nodemap)
72826 return UA_STATUSCODE_BADOUTOFMEMORY;
72827 nodemap->sizePrimeIndex = higher_prime_index(UA_NODEMAP_MINSIZE);
72828 nodemap->size = primes[nodemap->sizePrimeIndex];
72829 nodemap->count = 0;
72830 nodemap->slots = (UA_NodeMapSlot*)
72831 UA_calloc(nmemb: nodemap->size, size: sizeof(UA_NodeMapSlot));
72832 if(!nodemap->slots) {
72833 UA_free(ptr: nodemap);
72834 return UA_STATUSCODE_BADOUTOFMEMORY;
72835 }
72836
72837 nodemap->referenceTypeCounter = 0;
72838
72839 /* Populate the nodestore */
72840 ns->context = nodemap;
72841 ns->clear = UA_NodeMap_delete;
72842 ns->newNode = UA_NodeMap_newNode;
72843 ns->deleteNode = UA_NodeMap_deleteNode;
72844 ns->getNode = UA_NodeMap_getNode;
72845 ns->releaseNode = UA_NodeMap_releaseNode;
72846 ns->getNodeCopy = UA_NodeMap_getNodeCopy;
72847 ns->insertNode = UA_NodeMap_insertNode;
72848 ns->replaceNode = UA_NodeMap_replaceNode;
72849 ns->removeNode = UA_NodeMap_removeNode;
72850 ns->getReferenceTypeId = UA_NodeMap_getReferenceTypeId;
72851 ns->iterate = UA_NodeMap_iterate;
72852 return UA_STATUSCODE_GOOD;
72853}
72854
72855/**** amalgamated original file "/plugins/ua_config_default.c" ****/
72856
72857/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
72858 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
72859 *
72860 * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
72861 * Copyright 2017 (c) Julian Grothoff
72862 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
72863 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
72864 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
72865 * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
72866 * Copyright 2018 (c) Fabian Arndt, Root-Core
72867 * Copyright 2019 (c) Kalycito Infotech Private Limited
72868 * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
72869 * Copyright 2020 (c) Wind River Systems, Inc.
72870 */
72871
72872#ifdef UA_ENABLE_WEBSOCKET_SERVER
72873#endif
72874
72875/* Struct initialization works across ANSI C/C99/C++ if it is done when the
72876 * variable is first declared. Assigning values to existing structs is
72877 * heterogeneous across the three. */
72878static UA_INLINE UA_UInt32Range
72879UA_UINT32RANGE(UA_UInt32 min, UA_UInt32 max) {
72880 UA_UInt32Range range = {min, max};
72881 return range;
72882}
72883
72884static UA_INLINE UA_DurationRange
72885UA_DURATIONRANGE(UA_Duration min, UA_Duration max) {
72886 UA_DurationRange range = {min, max};
72887 return range;
72888}
72889
72890UA_Server *
72891UA_Server_new(void) {
72892 UA_ServerConfig config;
72893 memset(s: &config, c: 0, n: sizeof(UA_ServerConfig));
72894 /* Set a default logger and NodeStore for the initialization */
72895 config.logger = UA_Log_Stdout_;
72896 if(UA_STATUSCODE_GOOD != UA_Nodestore_HashMap(ns: &config.nodestore)) {
72897 return NULL;
72898 }
72899
72900 return UA_Server_newWithConfig(config: &config);
72901}
72902
72903/*******************************/
72904/* Default Connection Settings */
72905/*******************************/
72906
72907const UA_ConnectionConfig UA_ConnectionConfig_default = {
72908 0, /* .protocolVersion */
72909 2 << 16, /* .sendBufferSize, 64k per chunk */
72910 2 << 16, /* .recvBufferSize, 64k per chunk */
72911 2 << 29, /* .localMaxMessageSize, 512 MB */
72912 2 << 29, /* .remoteMaxMessageSize, 512 MB */
72913 2 << 14, /* .localMaxChunkCount, 16k */
72914 2 << 14 /* .remoteMaxChunkCount, 16k */
72915};
72916
72917/***************************/
72918/* Default Server Settings */
72919/***************************/
72920
72921#define MANUFACTURER_NAME "open62541"
72922#define PRODUCT_NAME "open62541 OPC UA Server"
72923#define PRODUCT_URI "http://open62541.org"
72924#define APPLICATION_NAME "open62541-based OPC UA Application"
72925#define APPLICATION_URI "urn:unconfigured:application"
72926#define APPLICATION_URI_SERVER "urn:open62541.server.application"
72927
72928#define STRINGIFY(arg) #arg
72929#define VERSION(MAJOR, MINOR, PATCH, LABEL) \
72930 STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(PATCH) LABEL
72931
72932static UA_StatusCode
72933createEndpoint(UA_ServerConfig *conf, UA_EndpointDescription *endpoint,
72934 const UA_SecurityPolicy *securityPolicy,
72935 UA_MessageSecurityMode securityMode) {
72936 UA_EndpointDescription_init(p: endpoint);
72937
72938 endpoint->securityMode = securityMode;
72939 UA_String_copy(src: &securityPolicy->policyUri, dst: &endpoint->securityPolicyUri);
72940 endpoint->transportProfileUri =
72941 UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
72942
72943 /* Add security level value for the corresponding message security mode */
72944 endpoint->securityLevel = (UA_Byte) securityMode;
72945
72946 /* Enable all login mechanisms from the access control plugin */
72947 UA_StatusCode retval = UA_Array_copy(src: conf->accessControl.userTokenPolicies,
72948 size: conf->accessControl.userTokenPoliciesSize,
72949 dst: (void **)&endpoint->userIdentityTokens,
72950 type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
72951 if(retval != UA_STATUSCODE_GOOD){
72952 UA_String_clear(p: &endpoint->securityPolicyUri);
72953 UA_String_clear(p: &endpoint->transportProfileUri);
72954 return retval;
72955 }
72956 endpoint->userIdentityTokensSize = conf->accessControl.userTokenPoliciesSize;
72957
72958 UA_String_copy(src: &securityPolicy->localCertificate, dst: &endpoint->serverCertificate);
72959 UA_ApplicationDescription_copy(src: &conf->applicationDescription, dst: &endpoint->server);
72960
72961 return UA_STATUSCODE_GOOD;
72962}
72963
72964static const size_t usernamePasswordsSize = 2;
72965static UA_UsernamePasswordLogin usernamePasswords[2] = {
72966 {UA_STRING_STATIC("user1"), UA_STRING_STATIC("password")},
72967 {UA_STRING_STATIC("user2"), UA_STRING_STATIC("password1")}};
72968
72969static UA_StatusCode
72970setDefaultConfig(UA_ServerConfig *conf) {
72971 if(!conf)
72972 return UA_STATUSCODE_BADINVALIDARGUMENT;
72973
72974 if(conf->nodestore.context == NULL)
72975 UA_Nodestore_HashMap(ns: &conf->nodestore);
72976
72977 /* --> Start setting the default static config <-- */
72978 /* Allow user to set his own logger */
72979 if(!conf->logger.log)
72980 conf->logger = UA_Log_Stdout_;
72981
72982 conf->shutdownDelay = 0.0;
72983
72984 /* Server Description */
72985 UA_BuildInfo_clear(p: &conf->buildInfo);
72986 conf->buildInfo.productUri = UA_STRING_ALLOC(PRODUCT_URI);
72987 conf->buildInfo.manufacturerName = UA_STRING_ALLOC(MANUFACTURER_NAME);
72988 conf->buildInfo.productName = UA_STRING_ALLOC(PRODUCT_NAME);
72989 conf->buildInfo.softwareVersion =
72990 UA_STRING_ALLOC(VERSION(UA_OPEN62541_VER_MAJOR, UA_OPEN62541_VER_MINOR,
72991 UA_OPEN62541_VER_PATCH, UA_OPEN62541_VER_LABEL));
72992#ifdef UA_PACK_DEBIAN
72993 conf->buildInfo.buildNumber = UA_STRING_ALLOC("deb");
72994#else
72995 conf->buildInfo.buildNumber = UA_STRING_ALLOC(__DATE__ " " __TIME__);
72996#endif
72997 conf->buildInfo.buildDate = UA_DateTime_now();
72998
72999 UA_ApplicationDescription_clear(p: &conf->applicationDescription);
73000 conf->applicationDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI_SERVER);
73001 conf->applicationDescription.productUri = UA_STRING_ALLOC(PRODUCT_URI);
73002 conf->applicationDescription.applicationName =
73003 UA_LOCALIZEDTEXT_ALLOC(locale: "en", APPLICATION_NAME);
73004 conf->applicationDescription.applicationType = UA_APPLICATIONTYPE_SERVER;
73005 /* conf->applicationDescription.gatewayServerUri = UA_STRING_NULL; */
73006 /* conf->applicationDescription.discoveryProfileUri = UA_STRING_NULL; */
73007 /* conf->applicationDescription.discoveryUrlsSize = 0; */
73008 /* conf->applicationDescription.discoveryUrls = NULL; */
73009
73010#ifdef UA_ENABLE_DISCOVERY_MULTICAST
73011 UA_MdnsDiscoveryConfiguration_clear(&conf->mdnsConfig);
73012 conf->mdnsInterfaceIP = UA_STRING_NULL;
73013# if !defined(UA_HAS_GETIFADDR)
73014 conf->mdnsIpAddressList = NULL;
73015 conf->mdnsIpAddressListSize = 0;
73016# endif
73017#endif
73018
73019 /* Custom DataTypes */
73020 /* conf->customDataTypesSize = 0; */
73021 /* conf->customDataTypes = NULL; */
73022
73023 /* Networking */
73024 /* conf->networkLayersSize = 0; */
73025 /* conf->networkLayers = NULL; */
73026 /* conf->customHostname = UA_STRING_NULL; */
73027
73028 /* Endpoints */
73029 /* conf->endpoints = {0, NULL}; */
73030
73031 /* Certificate Verification that accepts every certificate. Can be
73032 * overwritten when the policy is specialized. */
73033 UA_CertificateVerification_AcceptAll(cv: &conf->certificateVerification);
73034
73035 /* * Global Node Lifecycle * */
73036 /* conf->nodeLifecycle.constructor = NULL; */
73037 /* conf->nodeLifecycle.destructor = NULL; */
73038 /* conf->nodeLifecycle.createOptionalChild = NULL; */
73039 /* conf->nodeLifecycle.generateChildNodeId = NULL; */
73040 conf->modellingRulesOnInstances = UA_TRUE;
73041
73042 /* Limits for SecureChannels */
73043 conf->maxSecureChannels = 40;
73044 conf->maxSecurityTokenLifetime = 10 * 60 * 1000; /* 10 minutes */
73045
73046 /* Limits for Sessions */
73047 conf->maxSessions = 100;
73048 conf->maxSessionTimeout = 60.0 * 60.0 * 1000.0; /* 1h */
73049
73050#ifdef UA_ENABLE_SUBSCRIPTIONS
73051 /* Limits for Subscriptions */
73052 conf->publishingIntervalLimits = UA_DURATIONRANGE(min: 100.0, max: 3600.0 * 1000.0);
73053 conf->lifeTimeCountLimits = UA_UINT32RANGE(min: 3, max: 15000);
73054 conf->keepAliveCountLimits = UA_UINT32RANGE(min: 1, max: 100);
73055 conf->maxNotificationsPerPublish = 1000;
73056 conf->enableRetransmissionQueue = true;
73057 conf->maxRetransmissionQueueSize = 0; /* unlimited */
73058# ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
73059 conf->maxEventsPerNode = 0; /* unlimited */
73060# endif
73061
73062 /* Limits for MonitoredItems */
73063 conf->samplingIntervalLimits = UA_DURATIONRANGE(min: 50.0, max: 24.0 * 3600.0 * 1000.0);
73064 conf->queueSizeLimits = UA_UINT32RANGE(min: 1, max: 100);
73065#endif
73066
73067#ifdef UA_ENABLE_DISCOVERY
73068 conf->discoveryCleanupTimeout = 60 * 60;
73069#endif
73070
73071#ifdef UA_ENABLE_HISTORIZING
73072 /* conf->accessHistoryDataCapability = UA_FALSE; */
73073 /* conf->maxReturnDataValues = 0; */
73074
73075 /* conf->accessHistoryEventsCapability = UA_FALSE; */
73076 /* conf->maxReturnEventValues = 0; */
73077
73078 /* conf->insertDataCapability = UA_FALSE; */
73079 /* conf->insertEventCapability = UA_FALSE; */
73080 /* conf->insertAnnotationsCapability = UA_FALSE; */
73081
73082 /* conf->replaceDataCapability = UA_FALSE; */
73083 /* conf->replaceEventCapability = UA_FALSE; */
73084
73085 /* conf->updateDataCapability = UA_FALSE; */
73086 /* conf->updateEventCapability = UA_FALSE; */
73087
73088 /* conf->deleteRawCapability = UA_FALSE; */
73089 /* conf->deleteEventCapability = UA_FALSE; */
73090 /* conf->deleteAtTimeDataCapability = UA_FALSE; */
73091#endif
73092
73093#if UA_MULTITHREADING >= 100
73094 conf->maxAsyncOperationQueueSize = 0;
73095 conf->asyncOperationTimeout = 120000; /* Async Operation Timeout in ms (2 minutes) */
73096#endif
73097
73098 /* --> Finish setting the default static config <-- */
73099
73100 return UA_STATUSCODE_GOOD;
73101}
73102
73103UA_EXPORT UA_StatusCode
73104UA_ServerConfig_setBasics(UA_ServerConfig* conf) {
73105 UA_StatusCode res = setDefaultConfig(conf);
73106 UA_LOG_WARNING(logger: &conf->logger, category: UA_LOGCATEGORY_USERLAND,
73107 msg: "AcceptAll Certificate Verification. "
73108 "Any remote certificate will be accepted.");
73109 return res;
73110}
73111
73112static UA_StatusCode
73113addDefaultNetworkLayers(UA_ServerConfig *conf, UA_UInt16 portNumber,
73114 UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
73115 return UA_ServerConfig_addNetworkLayerTCP(conf, portNumber, sendBufferSize, recvBufferSize);
73116}
73117
73118#ifdef UA_ENABLE_WEBSOCKET_SERVER
73119UA_EXPORT UA_StatusCode
73120UA_ServerConfig_addNetworkLayerWS(UA_ServerConfig *conf, UA_UInt16 portNumber,
73121 UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize, const UA_ByteString* certificate, const UA_ByteString* privateKey) {
73122 /* Add a network layer */
73123 UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
73124 UA_realloc(conf->networkLayers,
73125 sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
73126 if(!tmp)
73127 return UA_STATUSCODE_BADOUTOFMEMORY;
73128 conf->networkLayers = tmp;
73129
73130 UA_ConnectionConfig config = UA_ConnectionConfig_default;
73131 if(sendBufferSize > 0)
73132 config.sendBufferSize = sendBufferSize;
73133 if(recvBufferSize > 0)
73134 config.recvBufferSize = recvBufferSize;
73135
73136 conf->networkLayers[conf->networkLayersSize] =
73137 UA_ServerNetworkLayerWS(config, portNumber, certificate, privateKey);
73138 if(!conf->networkLayers[conf->networkLayersSize].handle)
73139 return UA_STATUSCODE_BADOUTOFMEMORY;
73140 conf->networkLayersSize++;
73141
73142 return UA_STATUSCODE_GOOD;
73143}
73144#endif
73145
73146UA_EXPORT UA_StatusCode
73147UA_ServerConfig_addNetworkLayerTCP(UA_ServerConfig *conf, UA_UInt16 portNumber,
73148 UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
73149 /* Add a network layer */
73150 UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
73151 UA_realloc(ptr: conf->networkLayers,
73152 size: sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
73153 if(!tmp)
73154 return UA_STATUSCODE_BADOUTOFMEMORY;
73155 conf->networkLayers = tmp;
73156
73157 UA_ConnectionConfig config = UA_ConnectionConfig_default;
73158 if (sendBufferSize > 0)
73159 config.sendBufferSize = sendBufferSize;
73160 if (recvBufferSize > 0)
73161 config.recvBufferSize = recvBufferSize;
73162
73163 conf->networkLayers[conf->networkLayersSize] =
73164 UA_ServerNetworkLayerTCP(config, port: portNumber, maxConnections: 0);
73165 if (!conf->networkLayers[conf->networkLayersSize].handle)
73166 return UA_STATUSCODE_BADOUTOFMEMORY;
73167 conf->networkLayersSize++;
73168
73169 return UA_STATUSCODE_GOOD;
73170}
73171
73172UA_EXPORT UA_StatusCode
73173UA_ServerConfig_addSecurityPolicyNone(UA_ServerConfig *config,
73174 const UA_ByteString *certificate) {
73175 /* Allocate the SecurityPolicies */
73176 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73177 UA_realloc(ptr: config->securityPolicies,
73178 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73179 if(!tmp)
73180 return UA_STATUSCODE_BADOUTOFMEMORY;
73181 config->securityPolicies = tmp;
73182
73183 /* Populate the SecurityPolicies */
73184 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73185 if(certificate)
73186 localCertificate = *certificate;
73187 UA_StatusCode retval =
73188 UA_SecurityPolicy_None(policy: &config->securityPolicies[config->securityPoliciesSize],
73189 localCertificate, logger: &config->logger);
73190 if(retval != UA_STATUSCODE_GOOD) {
73191 if(config->securityPoliciesSize == 0) {
73192 UA_free(ptr: config->securityPolicies);
73193 config->securityPolicies = NULL;
73194 }
73195 return retval;
73196 }
73197
73198 config->securityPoliciesSize++;
73199 return UA_STATUSCODE_GOOD;
73200}
73201
73202UA_EXPORT UA_StatusCode
73203UA_ServerConfig_addEndpoint(UA_ServerConfig *config, const UA_String securityPolicyUri,
73204 UA_MessageSecurityMode securityMode) {
73205 /* Allocate the endpoint */
73206 UA_EndpointDescription *tmp = (UA_EndpointDescription *)
73207 UA_realloc(ptr: config->endpoints,
73208 size: sizeof(UA_EndpointDescription) * (1 + config->endpointsSize));
73209 if(!tmp) {
73210 return UA_STATUSCODE_BADOUTOFMEMORY;
73211 }
73212 config->endpoints = tmp;
73213
73214 /* Lookup the security policy */
73215 const UA_SecurityPolicy *policy = NULL;
73216 for (size_t i = 0; i < config->securityPoliciesSize; ++i) {
73217 if (UA_String_equal(s1: &securityPolicyUri, s2: &config->securityPolicies[i].policyUri)) {
73218 policy = &config->securityPolicies[i];
73219 break;
73220 }
73221 }
73222 if (!policy)
73223 return UA_STATUSCODE_BADINVALIDARGUMENT;
73224
73225 /* Populate the endpoint */
73226 UA_StatusCode retval =
73227 createEndpoint(conf: config, endpoint: &config->endpoints[config->endpointsSize],
73228 securityPolicy: policy, securityMode);
73229 if(retval != UA_STATUSCODE_GOOD)
73230 return retval;
73231 config->endpointsSize++;
73232
73233 return UA_STATUSCODE_GOOD;
73234}
73235
73236UA_EXPORT UA_StatusCode
73237UA_ServerConfig_addAllEndpoints(UA_ServerConfig *config) {
73238 /* Allocate the endpoints */
73239 UA_EndpointDescription * tmp = (UA_EndpointDescription *)
73240 UA_realloc(ptr: config->endpoints,
73241 size: sizeof(UA_EndpointDescription) *
73242 (2 * config->securityPoliciesSize + config->endpointsSize));
73243 if(!tmp) {
73244 return UA_STATUSCODE_BADOUTOFMEMORY;
73245 }
73246 config->endpoints = tmp;
73247
73248 /* Populate the endpoints */
73249 for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
73250 if(UA_String_equal(s1: &UA_SECURITY_POLICY_NONE_URI, s2: &config->securityPolicies[i].policyUri)) {
73251 UA_StatusCode retval =
73252 createEndpoint(conf: config, endpoint: &config->endpoints[config->endpointsSize],
73253 securityPolicy: &config->securityPolicies[i], securityMode: UA_MESSAGESECURITYMODE_NONE);
73254 if(retval != UA_STATUSCODE_GOOD)
73255 return retval;
73256 config->endpointsSize++;
73257 } else {
73258 UA_StatusCode retval =
73259 createEndpoint(conf: config, endpoint: &config->endpoints[config->endpointsSize],
73260 securityPolicy: &config->securityPolicies[i], securityMode: UA_MESSAGESECURITYMODE_SIGN);
73261 if(retval != UA_STATUSCODE_GOOD)
73262 return retval;
73263 config->endpointsSize++;
73264
73265 retval = createEndpoint(conf: config, endpoint: &config->endpoints[config->endpointsSize],
73266 securityPolicy: &config->securityPolicies[i],
73267 securityMode: UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
73268 if(retval != UA_STATUSCODE_GOOD)
73269 return retval;
73270 config->endpointsSize++;
73271 }
73272 }
73273
73274 return UA_STATUSCODE_GOOD;
73275}
73276
73277UA_EXPORT UA_StatusCode
73278UA_ServerConfig_setMinimalCustomBuffer(UA_ServerConfig *config, UA_UInt16 portNumber,
73279 const UA_ByteString *certificate,
73280 UA_UInt32 sendBufferSize,
73281 UA_UInt32 recvBufferSize) {
73282 if(!config)
73283 return UA_STATUSCODE_BADINVALIDARGUMENT;
73284
73285 UA_StatusCode retval = setDefaultConfig(config);
73286 if(retval != UA_STATUSCODE_GOOD) {
73287 UA_ServerConfig_clean(config);
73288 return retval;
73289 }
73290
73291 retval = addDefaultNetworkLayers(conf: config, portNumber, sendBufferSize, recvBufferSize);
73292 if(retval != UA_STATUSCODE_GOOD) {
73293 UA_ServerConfig_clean(config);
73294 return retval;
73295 }
73296
73297 /* Allocate the SecurityPolicies */
73298 retval = UA_ServerConfig_addSecurityPolicyNone(config, certificate);
73299 if(retval != UA_STATUSCODE_GOOD) {
73300 UA_ServerConfig_clean(config);
73301 return retval;
73302 }
73303
73304 /* Initialize the Access Control plugin */
73305 retval = UA_AccessControl_default(config, true, NULL,
73306 userTokenPolicyUri: &config->securityPolicies[config->securityPoliciesSize-1].policyUri,
73307 usernamePasswordLoginSize: usernamePasswordsSize, usernamePasswordLogin: usernamePasswords);
73308 if(retval != UA_STATUSCODE_GOOD) {
73309 UA_ServerConfig_clean(config);
73310 return retval;
73311 }
73312
73313 /* Allocate the endpoint */
73314 retval = UA_ServerConfig_addEndpoint(config, securityPolicyUri: UA_SECURITY_POLICY_NONE_URI,
73315 securityMode: UA_MESSAGESECURITYMODE_NONE);
73316 if(retval != UA_STATUSCODE_GOOD) {
73317 UA_ServerConfig_clean(config);
73318 return retval;
73319 }
73320
73321 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73322 msg: "AcceptAll Certificate Verification. "
73323 "Any remote certificate will be accepted.");
73324
73325 return UA_STATUSCODE_GOOD;
73326}
73327
73328#ifdef UA_ENABLE_ENCRYPTION
73329
73330UA_EXPORT UA_StatusCode
73331UA_ServerConfig_addSecurityPolicyBasic128Rsa15(UA_ServerConfig *config,
73332 const UA_ByteString *certificate,
73333 const UA_ByteString *privateKey) {
73334 /* Allocate the SecurityPolicies */
73335 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73336 UA_realloc(ptr: config->securityPolicies,
73337 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73338 if(!tmp)
73339 return UA_STATUSCODE_BADOUTOFMEMORY;
73340 config->securityPolicies = tmp;
73341
73342 /* Populate the SecurityPolicies */
73343 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73344 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73345 if(certificate)
73346 localCertificate = *certificate;
73347 if(privateKey)
73348 localPrivateKey = *privateKey;
73349 UA_StatusCode retval =
73350 UA_SecurityPolicy_Basic128Rsa15(policy: &config->securityPolicies[config->securityPoliciesSize],
73351 localCertificate, localPrivateKey, logger: &config->logger);
73352 if(retval != UA_STATUSCODE_GOOD) {
73353 if(config->securityPoliciesSize == 0) {
73354 UA_free(ptr: config->securityPolicies);
73355 config->securityPolicies = NULL;
73356 }
73357 return retval;
73358 }
73359
73360 config->securityPoliciesSize++;
73361 return UA_STATUSCODE_GOOD;
73362}
73363
73364UA_EXPORT UA_StatusCode
73365UA_ServerConfig_addSecurityPolicyBasic256(UA_ServerConfig *config,
73366 const UA_ByteString *certificate,
73367 const UA_ByteString *privateKey) {
73368 /* Allocate the SecurityPolicies */
73369 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73370 UA_realloc(ptr: config->securityPolicies,
73371 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73372 if(!tmp)
73373 return UA_STATUSCODE_BADOUTOFMEMORY;
73374 config->securityPolicies = tmp;
73375
73376 /* Populate the SecurityPolicies */
73377 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73378 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73379 if(certificate)
73380 localCertificate = *certificate;
73381 if(privateKey)
73382 localPrivateKey = *privateKey;
73383 UA_StatusCode retval =
73384 UA_SecurityPolicy_Basic256(policy: &config->securityPolicies[config->securityPoliciesSize],
73385 localCertificate, localPrivateKey, logger: &config->logger);
73386 if(retval != UA_STATUSCODE_GOOD) {
73387 if(config->securityPoliciesSize == 0) {
73388 UA_free(ptr: config->securityPolicies);
73389 config->securityPolicies = NULL;
73390 }
73391 return retval;
73392 }
73393
73394 config->securityPoliciesSize++;
73395 return UA_STATUSCODE_GOOD;
73396}
73397
73398UA_EXPORT UA_StatusCode
73399UA_ServerConfig_addSecurityPolicyBasic256Sha256(UA_ServerConfig *config,
73400 const UA_ByteString *certificate,
73401 const UA_ByteString *privateKey) {
73402 /* Allocate the SecurityPolicies */
73403 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73404 UA_realloc(ptr: config->securityPolicies,
73405 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73406 if(!tmp)
73407 return UA_STATUSCODE_BADOUTOFMEMORY;
73408 config->securityPolicies = tmp;
73409
73410 /* Populate the SecurityPolicies */
73411 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73412 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73413 if(certificate)
73414 localCertificate = *certificate;
73415 if(privateKey)
73416 localPrivateKey = *privateKey;
73417 UA_StatusCode retval =
73418 UA_SecurityPolicy_Basic256Sha256(policy: &config->securityPolicies[config->securityPoliciesSize],
73419 localCertificate, localPrivateKey, logger: &config->logger);
73420 if(retval != UA_STATUSCODE_GOOD) {
73421 if(config->securityPoliciesSize == 0) {
73422 UA_free(ptr: config->securityPolicies);
73423 config->securityPolicies = NULL;
73424 }
73425 return retval;
73426 }
73427
73428 config->securityPoliciesSize++;
73429 return UA_STATUSCODE_GOOD;
73430}
73431
73432UA_EXPORT UA_StatusCode
73433UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(UA_ServerConfig *config,
73434 const UA_ByteString *certificate,
73435 const UA_ByteString *privateKey) {
73436 /* Allocate the SecurityPolicies */
73437 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73438 UA_realloc(ptr: config->securityPolicies,
73439 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73440 if(!tmp)
73441 return UA_STATUSCODE_BADOUTOFMEMORY;
73442 config->securityPolicies = tmp;
73443
73444 /* Populate the SecurityPolicies */
73445 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73446 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73447 if(certificate)
73448 localCertificate = *certificate;
73449 if(privateKey)
73450 localPrivateKey = *privateKey;
73451 UA_StatusCode retval =
73452 UA_SecurityPolicy_Aes128Sha256RsaOaep(policy: &config->securityPolicies[config->securityPoliciesSize],
73453 localCertificate, localPrivateKey, logger: &config->logger);
73454 if(retval != UA_STATUSCODE_GOOD) {
73455 if(config->securityPoliciesSize == 0) {
73456 UA_free(ptr: config->securityPolicies);
73457 config->securityPolicies = NULL;
73458 }
73459 return retval;
73460 }
73461
73462 config->securityPoliciesSize++;
73463 return UA_STATUSCODE_GOOD;
73464}
73465
73466/* Always returns UA_STATUSCODE_GOOD. Logs a warning if policies could not be added. */
73467UA_EXPORT UA_StatusCode
73468UA_ServerConfig_addAllSecurityPolicies(UA_ServerConfig *config,
73469 const UA_ByteString *certificate,
73470 const UA_ByteString *privateKey) {
73471 /* Populate the SecurityPolicies */
73472 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73473 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73474 if(certificate)
73475 localCertificate = *certificate;
73476 if(privateKey)
73477 localPrivateKey = *privateKey;
73478
73479 UA_StatusCode retval = UA_ServerConfig_addSecurityPolicyNone(config, certificate: &localCertificate);
73480 if(retval != UA_STATUSCODE_GOOD) {
73481 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73482 msg: "Could not add SecurityPolicy#None with error code %s",
73483 UA_StatusCode_name(code: retval));
73484 }
73485
73486 retval = UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, certificate: &localCertificate, privateKey: &localPrivateKey);
73487 if(retval != UA_STATUSCODE_GOOD) {
73488 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73489 msg: "Could not add SecurityPolicy#Basic128Rsa15 with error code %s",
73490 UA_StatusCode_name(code: retval));
73491 }
73492
73493 retval = UA_ServerConfig_addSecurityPolicyBasic256(config, certificate: &localCertificate, privateKey: &localPrivateKey);
73494 if(retval != UA_STATUSCODE_GOOD) {
73495 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73496 msg: "Could not add SecurityPolicy#Basic256 with error code %s",
73497 UA_StatusCode_name(code: retval));
73498 }
73499
73500 retval = UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, certificate: &localCertificate, privateKey: &localPrivateKey);
73501 if(retval != UA_STATUSCODE_GOOD) {
73502 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73503 msg: "Could not add SecurityPolicy#Basic256Sha256 with error code %s",
73504 UA_StatusCode_name(code: retval));
73505 }
73506
73507 retval = UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(config, certificate: &localCertificate, privateKey: &localPrivateKey);
73508 if(retval != UA_STATUSCODE_GOOD) {
73509 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73510 msg: "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s",
73511 UA_StatusCode_name(code: retval));
73512 }
73513
73514 return UA_STATUSCODE_GOOD;
73515}
73516
73517UA_EXPORT UA_StatusCode
73518UA_ServerConfig_setDefaultWithSecurityPolicies(UA_ServerConfig *conf,
73519 UA_UInt16 portNumber,
73520 const UA_ByteString *certificate,
73521 const UA_ByteString *privateKey,
73522 const UA_ByteString *trustList,
73523 size_t trustListSize,
73524 const UA_ByteString *issuerList,
73525 size_t issuerListSize,
73526 const UA_ByteString *revocationList,
73527 size_t revocationListSize) {
73528 UA_StatusCode retval = setDefaultConfig(conf);
73529 if(retval != UA_STATUSCODE_GOOD) {
73530 UA_ServerConfig_clean(config: conf);
73531 return retval;
73532 }
73533
73534 retval = UA_CertificateVerification_Trustlist(cv: &conf->certificateVerification,
73535 certificateTrustList: trustList, certificateTrustListSize: trustListSize,
73536 certificateIssuerList: issuerList, certificateIssuerListSize: issuerListSize,
73537 certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize);
73538 if (retval != UA_STATUSCODE_GOOD)
73539 return retval;
73540
73541 retval = addDefaultNetworkLayers(conf, portNumber, sendBufferSize: 0, recvBufferSize: 0);
73542 if(retval != UA_STATUSCODE_GOOD) {
73543 UA_ServerConfig_clean(config: conf);
73544 return retval;
73545 }
73546
73547 retval = UA_ServerConfig_addAllSecurityPolicies(config: conf, certificate, privateKey);
73548 if(retval != UA_STATUSCODE_GOOD) {
73549 UA_ServerConfig_clean(config: conf);
73550 return retval;
73551 }
73552
73553 UA_CertificateVerification accessControlVerification;
73554 retval = UA_CertificateVerification_Trustlist(cv: &accessControlVerification,
73555 certificateTrustList: trustList, certificateTrustListSize: trustListSize,
73556 certificateIssuerList: issuerList, certificateIssuerListSize: issuerListSize,
73557 certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize);
73558 retval |= UA_AccessControl_default(config: conf, true, verifyX509: &accessControlVerification,
73559 userTokenPolicyUri: &conf->securityPolicies[conf->securityPoliciesSize-1].policyUri,
73560 usernamePasswordLoginSize: usernamePasswordsSize, usernamePasswordLogin: usernamePasswords);
73561 if(retval != UA_STATUSCODE_GOOD) {
73562 UA_ServerConfig_clean(config: conf);
73563 return retval;
73564 }
73565
73566 retval = UA_ServerConfig_addAllEndpoints(config: conf);
73567 if(retval != UA_STATUSCODE_GOOD) {
73568 UA_ServerConfig_clean(config: conf);
73569 return retval;
73570 }
73571
73572 return UA_STATUSCODE_GOOD;
73573}
73574
73575#endif
73576
73577/***************************/
73578/* Default Client Settings */
73579/***************************/
73580
73581UA_Client * UA_Client_new(void) {
73582 UA_ClientConfig config;
73583 memset(s: &config, c: 0, n: sizeof(UA_ClientConfig));
73584 config.logger.log = UA_Log_Stdout_log;
73585 config.logger.context = NULL;
73586 config.logger.clear = UA_Log_Stdout_clear;
73587 return UA_Client_newWithConfig(config: &config);
73588}
73589
73590UA_StatusCode
73591UA_ClientConfig_setDefault(UA_ClientConfig *config) {
73592 config->timeout = 5000;
73593 config->secureChannelLifeTime = 10 * 60 * 1000; /* 10 minutes */
73594
73595 if(!config->logger.log) {
73596 config->logger.log = UA_Log_Stdout_log;
73597 config->logger.context = NULL;
73598 config->logger.clear = UA_Log_Stdout_clear;
73599 }
73600
73601 if (config->sessionLocaleIdsSize > 0 && config->sessionLocaleIds) {
73602 UA_Array_delete(p: config->sessionLocaleIds, size: config->sessionLocaleIdsSize, type: &UA_TYPES[UA_TYPES_LOCALEID]);
73603 }
73604 config->sessionLocaleIds = NULL;
73605 config->sessionLocaleIds = 0;
73606
73607 config->localConnectionConfig = UA_ConnectionConfig_default;
73608
73609 /* Certificate Verification that accepts every certificate. Can be
73610 * overwritten when the policy is specialized. */
73611 UA_CertificateVerification_AcceptAll(cv: &config->certificateVerification);
73612 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73613 msg: "AcceptAll Certificate Verification. "
73614 "Any remote certificate will be accepted.");
73615
73616 /* With encryption enabled, the applicationUri needs to match the URI from
73617 * the certificate */
73618 config->clientDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI);
73619 config->clientDescription.applicationType = UA_APPLICATIONTYPE_CLIENT;
73620
73621 if(config->securityPoliciesSize > 0) {
73622 UA_LOG_ERROR(logger: &config->logger, category: UA_LOGCATEGORY_NETWORK,
73623 msg: "Could not initialize a config that already has SecurityPolicies");
73624 return UA_STATUSCODE_BADINTERNALERROR;
73625 }
73626
73627 config->securityPolicies = (UA_SecurityPolicy*)UA_malloc(size: sizeof(UA_SecurityPolicy));
73628 if(!config->securityPolicies)
73629 return UA_STATUSCODE_BADOUTOFMEMORY;
73630 UA_StatusCode retval = UA_SecurityPolicy_None(policy: config->securityPolicies,
73631 localCertificate: UA_BYTESTRING_NULL, logger: &config->logger);
73632 if(retval != UA_STATUSCODE_GOOD) {
73633 UA_free(ptr: config->securityPolicies);
73634 config->securityPolicies = NULL;
73635 return retval;
73636 }
73637 config->securityPoliciesSize = 1;
73638
73639 config->initConnectionFunc = UA_ClientConnectionTCP_init; /* for async client */
73640 config->pollConnectionFunc = UA_ClientConnectionTCP_poll; /* for async connection */
73641
73642 config->customDataTypes = NULL;
73643 config->stateCallback = NULL;
73644 config->connectivityCheckInterval = 0;
73645
73646 config->requestedSessionTimeout = 1200000; /* requestedSessionTimeout */
73647
73648 config->inactivityCallback = NULL;
73649 config->clientContext = NULL;
73650
73651#ifdef UA_ENABLE_SUBSCRIPTIONS
73652 config->outStandingPublishRequests = 10;
73653 config->subscriptionInactivityCallback = NULL;
73654#endif
73655
73656 return UA_STATUSCODE_GOOD;
73657}
73658
73659#ifdef UA_ENABLE_ENCRYPTION
73660UA_StatusCode
73661UA_ClientConfig_setDefaultEncryption(UA_ClientConfig *config,
73662 UA_ByteString localCertificate, UA_ByteString privateKey,
73663 const UA_ByteString *trustList, size_t trustListSize,
73664 const UA_ByteString *revocationList, size_t revocationListSize) {
73665 UA_StatusCode retval = UA_ClientConfig_setDefault(config);
73666 if(retval != UA_STATUSCODE_GOOD)
73667 return retval;
73668
73669 retval = UA_CertificateVerification_Trustlist(cv: &config->certificateVerification,
73670 certificateTrustList: trustList, certificateTrustListSize: trustListSize,
73671 NULL, certificateIssuerListSize: 0,
73672 certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize);
73673 if(retval != UA_STATUSCODE_GOOD)
73674 return retval;
73675
73676 /* Populate SecurityPolicies */
73677 UA_SecurityPolicy *sp = (UA_SecurityPolicy*)
73678 UA_realloc(ptr: config->securityPolicies, size: sizeof(UA_SecurityPolicy) * 5);
73679 if(!sp)
73680 return UA_STATUSCODE_BADOUTOFMEMORY;
73681 config->securityPolicies = sp;
73682
73683 retval = UA_SecurityPolicy_Basic128Rsa15(policy: &config->securityPolicies[config->securityPoliciesSize],
73684 localCertificate, localPrivateKey: privateKey, logger: &config->logger);
73685 if(retval == UA_STATUSCODE_GOOD) {
73686 ++config->securityPoliciesSize;
73687 } else {
73688 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73689 msg: "Could not add SecurityPolicy#Basic128Rsa15 with error code %s",
73690 UA_StatusCode_name(code: retval));
73691 }
73692
73693 retval = UA_SecurityPolicy_Basic256(policy: &config->securityPolicies[config->securityPoliciesSize],
73694 localCertificate, localPrivateKey: privateKey, logger: &config->logger);
73695 if(retval == UA_STATUSCODE_GOOD) {
73696 ++config->securityPoliciesSize;
73697 } else {
73698 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73699 msg: "Could not add SecurityPolicy#Basic256 with error code %s",
73700 UA_StatusCode_name(code: retval));
73701 }
73702
73703 retval = UA_SecurityPolicy_Basic256Sha256(policy: &config->securityPolicies[config->securityPoliciesSize],
73704 localCertificate, localPrivateKey: privateKey, logger: &config->logger);
73705 if(retval == UA_STATUSCODE_GOOD) {
73706 ++config->securityPoliciesSize;
73707 } else {
73708 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73709 msg: "Could not add SecurityPolicy#Basic256Sha256 with error code %s",
73710 UA_StatusCode_name(code: retval));
73711 }
73712
73713 retval = UA_SecurityPolicy_Aes128Sha256RsaOaep(policy: &config->securityPolicies[config->securityPoliciesSize],
73714 localCertificate, localPrivateKey: privateKey, logger: &config->logger);
73715 if(retval == UA_STATUSCODE_GOOD) {
73716 ++config->securityPoliciesSize;
73717 } else {
73718 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73719 msg: "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s",
73720 UA_StatusCode_name(code: retval));
73721 }
73722
73723 if(config->securityPoliciesSize == 0) {
73724 UA_free(ptr: config->securityPolicies);
73725 config->securityPolicies = NULL;
73726 }
73727
73728 return UA_STATUSCODE_GOOD;
73729}
73730#endif
73731
73732/**** amalgamated original file "/plugins/crypto/ua_pki_none.c" ****/
73733
73734/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
73735 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
73736 *
73737 * Copyright 2020 (c) Julius Pfrommer, Fraunhofer IOSB
73738 */
73739
73740
73741static UA_StatusCode
73742verifyCertificateAllowAll(void *verificationContext,
73743 const UA_ByteString *certificate) {
73744 return UA_STATUSCODE_GOOD;
73745}
73746
73747static UA_StatusCode
73748verifyApplicationURIAllowAll(void *verificationContext,
73749 const UA_ByteString *certificate,
73750 const UA_String *applicationURI) {
73751 return UA_STATUSCODE_GOOD;
73752}
73753
73754static void
73755clearVerifyAllowAll(UA_CertificateVerification *cv) {
73756
73757}
73758
73759void UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv) {
73760 cv->verifyCertificate = verifyCertificateAllowAll;
73761 cv->verifyApplicationURI = verifyApplicationURIAllowAll;
73762 cv->clear = clearVerifyAllowAll;
73763}
73764
73765/**** amalgamated original file "/plugins/crypto/ua_securitypolicy_none.c" ****/
73766
73767/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
73768 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
73769 *
73770 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
73771 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
73772 */
73773
73774
73775#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
73776#endif
73777
73778#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
73779#endif
73780
73781static UA_StatusCode
73782verify_none(void *channelContext,
73783 const UA_ByteString *message,
73784 const UA_ByteString *signature) {
73785 return UA_STATUSCODE_GOOD;
73786}
73787
73788static UA_StatusCode
73789sign_none(void *channelContext, const UA_ByteString *message,
73790 UA_ByteString *signature) {
73791 return UA_STATUSCODE_GOOD;
73792}
73793
73794static size_t
73795length_none(const void *channelContext) {
73796 return 0;
73797}
73798
73799static UA_StatusCode
73800encrypt_none(void *channelContext, UA_ByteString *data) {
73801 return UA_STATUSCODE_GOOD;
73802}
73803
73804static UA_StatusCode
73805decrypt_none(void *channelContext, UA_ByteString *data) {
73806 return UA_STATUSCODE_GOOD;
73807}
73808
73809static UA_StatusCode
73810makeThumbprint_none(const UA_SecurityPolicy *securityPolicy,
73811 const UA_ByteString *certificate,
73812 UA_ByteString *thumbprint) {
73813 return UA_STATUSCODE_GOOD;
73814}
73815
73816static UA_StatusCode
73817compareThumbprint_none(const UA_SecurityPolicy *securityPolicy,
73818 const UA_ByteString *certificateThumbprint) {
73819 return UA_STATUSCODE_GOOD;
73820}
73821
73822static UA_StatusCode
73823generateKey_none(void *policyContext, const UA_ByteString *secret,
73824 const UA_ByteString *seed, UA_ByteString *out) {
73825 return UA_STATUSCODE_GOOD;
73826}
73827
73828/* Use the non-cryptographic RNG to set the nonce */
73829static UA_StatusCode
73830generateNonce_none(void *policyContext, UA_ByteString *out) {
73831 if(out == NULL)
73832 return UA_STATUSCODE_BADINTERNALERROR;
73833
73834 if(out->length == 0)
73835 return UA_STATUSCODE_GOOD;
73836
73837 /* Fill blocks of four byte */
73838 size_t i = 0;
73839 while(i + 3 < out->length) {
73840 UA_UInt32 randNumber = UA_UInt32_random();
73841 memcpy(dest: &out->data[i], src: &randNumber, n: 4);
73842 i = i+4;
73843 }
73844
73845 /* Fill the remaining byte */
73846 UA_UInt32 randNumber = UA_UInt32_random();
73847 memcpy(dest: &out->data[i], src: &randNumber, n: out->length % 4);
73848
73849 return UA_STATUSCODE_GOOD;
73850}
73851
73852static UA_StatusCode
73853newContext_none(const UA_SecurityPolicy *securityPolicy,
73854 const UA_ByteString *remoteCertificate,
73855 void **channelContext) {
73856 return UA_STATUSCODE_GOOD;
73857}
73858
73859static void
73860deleteContext_none(void *channelContext) {
73861}
73862
73863static UA_StatusCode
73864setContextValue_none(void *channelContext,
73865 const UA_ByteString *key) {
73866 return UA_STATUSCODE_GOOD;
73867}
73868
73869static UA_StatusCode
73870compareCertificate_none(const void *channelContext,
73871 const UA_ByteString *certificate) {
73872 return UA_STATUSCODE_GOOD;
73873}
73874
73875static UA_StatusCode
73876updateCertificateAndPrivateKey_none(UA_SecurityPolicy *policy,
73877 const UA_ByteString newCertificate,
73878 const UA_ByteString newPrivateKey) {
73879 UA_ByteString_clear(p: &policy->localCertificate);
73880 UA_ByteString_copy(src: &newCertificate, dst: &policy->localCertificate);
73881 return UA_STATUSCODE_GOOD;
73882}
73883
73884
73885static void
73886policy_clear_none(UA_SecurityPolicy *policy) {
73887 UA_ByteString_clear(p: &policy->localCertificate);
73888}
73889
73890UA_StatusCode
73891UA_SecurityPolicy_None(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
73892 const UA_Logger *logger) {
73893 policy->policyContext = (void *)(uintptr_t)logger;
73894 policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None");
73895 policy->logger = logger;
73896
73897#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
73898 UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
73899#elif defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
73900 UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate);
73901#else
73902 UA_ByteString_copy(&localCertificate, &policy->localCertificate);
73903#endif
73904
73905 policy->symmetricModule.generateKey = generateKey_none;
73906 policy->symmetricModule.generateNonce = generateNonce_none;
73907
73908 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
73909 &policy->symmetricModule.cryptoModule.signatureAlgorithm;
73910 sym_signatureAlgorithm->uri = UA_STRING_NULL;
73911 sym_signatureAlgorithm->verify = verify_none;
73912 sym_signatureAlgorithm->sign = sign_none;
73913 sym_signatureAlgorithm->getLocalSignatureSize = length_none;
73914 sym_signatureAlgorithm->getRemoteSignatureSize = length_none;
73915 sym_signatureAlgorithm->getLocalKeyLength = length_none;
73916 sym_signatureAlgorithm->getRemoteKeyLength = length_none;
73917
73918 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
73919 &policy->symmetricModule.cryptoModule.encryptionAlgorithm;
73920 sym_encryptionAlgorithm->uri = UA_STRING_NULL;
73921 sym_encryptionAlgorithm->encrypt = encrypt_none;
73922 sym_encryptionAlgorithm->decrypt = decrypt_none;
73923 sym_encryptionAlgorithm->getLocalKeyLength = length_none;
73924 sym_encryptionAlgorithm->getRemoteKeyLength = length_none;
73925 sym_encryptionAlgorithm->getRemoteBlockSize = length_none;
73926 sym_encryptionAlgorithm->getRemotePlainTextBlockSize = length_none;
73927 policy->symmetricModule.secureChannelNonceLength = 0;
73928
73929 policy->asymmetricModule.makeCertificateThumbprint = makeThumbprint_none;
73930 policy->asymmetricModule.compareCertificateThumbprint = compareThumbprint_none;
73931
73932 // This only works for none since symmetric and asymmetric crypto modules do the same i.e. nothing
73933 policy->asymmetricModule.cryptoModule = policy->symmetricModule.cryptoModule;
73934
73935 // Use the same signing algorithm as for asymmetric signing
73936 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
73937
73938 policy->channelModule.newContext = newContext_none;
73939 policy->channelModule.deleteContext = deleteContext_none;
73940 policy->channelModule.setLocalSymEncryptingKey = setContextValue_none;
73941 policy->channelModule.setLocalSymSigningKey = setContextValue_none;
73942 policy->channelModule.setLocalSymIv = setContextValue_none;
73943 policy->channelModule.setRemoteSymEncryptingKey = setContextValue_none;
73944 policy->channelModule.setRemoteSymSigningKey = setContextValue_none;
73945 policy->channelModule.setRemoteSymIv = setContextValue_none;
73946 policy->channelModule.compareCertificate = compareCertificate_none;
73947 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_none;
73948 policy->clear = policy_clear_none;
73949
73950 return UA_STATUSCODE_GOOD;
73951}
73952
73953/**** amalgamated original file "/plugins/ua_log_syslog.c" ****/
73954
73955/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
73956 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
73957 *
73958 * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
73959 */
73960
73961
73962#if defined(__linux__) || defined(__unix__)
73963
73964#include <syslog.h>
73965
73966const char *syslogLevelNames[6] = {"trace", "debug", "info",
73967 "warn", "error", "fatal"};
73968const char *syslogCategoryNames[7] = {"network", "channel", "session", "server",
73969 "client", "userland", "securitypolicy"};
73970
73971#ifdef __clang__
73972__attribute__((__format__(__printf__, 4 , 0)))
73973#endif
73974static void
73975UA_Log_Syslog_log(void *context, UA_LogLevel level, UA_LogCategory category,
73976 const char *msg, va_list args) {
73977 /* Assume that context is casted to UA_LogLevel */
73978 if(context != NULL && (UA_LogLevel)(uintptr_t)context > level)
73979 return;
73980
73981 int priority = LOG_INFO;
73982 switch(level) {
73983 case UA_LOGLEVEL_DEBUG:
73984 priority = LOG_DEBUG;
73985 break;
73986 case UA_LOGLEVEL_INFO:
73987 priority = LOG_INFO;
73988 break;
73989 case UA_LOGLEVEL_WARNING:
73990 priority = LOG_WARNING;
73991 break;
73992 case UA_LOGLEVEL_ERROR:
73993 priority = LOG_ERR;
73994 break;
73995 case UA_LOGLEVEL_FATAL:
73996 priority = LOG_CRIT;
73997 break;
73998 case UA_LOGLEVEL_TRACE:
73999 default:
74000 return;
74001 }
74002
74003#define LOGBUFSIZE 512
74004 char logbuf[LOGBUFSIZE];
74005 int pos = snprintf(s: logbuf, LOGBUFSIZE, format: "[%s/%s] ",
74006 syslogLevelNames[level], syslogCategoryNames[category]);
74007 if(pos < 0) {
74008 syslog(LOG_WARNING, fmt: "Log message too long for syslog");
74009 return;
74010 }
74011 pos = vsnprintf(s: &logbuf[pos], LOGBUFSIZE - (size_t)pos, format: msg, arg: args);
74012 if(pos < 0) {
74013 syslog(LOG_WARNING, fmt: "Log message too long for syslog");
74014 return;
74015 }
74016
74017 syslog(pri: priority, fmt: "%s", logbuf);
74018}
74019
74020static void
74021UA_Log_Syslog_clear(void *logContext) {
74022 /* closelog is optional. We don't use it as several loggers might be
74023 * instantiated in parallel. */
74024 /* closelog(); */
74025}
74026
74027UA_Logger
74028UA_Log_Syslog(void) {
74029 return UA_Log_Syslog_withLevel(minlevel: UA_LOGLEVEL_TRACE);
74030}
74031
74032UA_Logger
74033UA_Log_Syslog_withLevel(UA_LogLevel minlevel) {
74034 UA_Logger logger = {UA_Log_Syslog_log, (void*)minlevel, UA_Log_Syslog_clear};
74035 return logger;
74036}
74037
74038#endif
74039
74040/**** amalgamated original file "/plugins/historydata/ua_history_data_backend_memory.c" ****/
74041
74042/* This Source Code Form is subject to the terms of the Mozilla Public
74043 * License, v. 2.0. If a copy of the MPL was not distributed with this
74044 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
74045 *
74046 * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler)
74047 */
74048
74049
74050#include <limits.h>
74051#include <string.h>
74052
74053typedef struct {
74054 UA_DateTime timestamp;
74055 UA_DataValue value;
74056} UA_DataValueMemoryStoreItem;
74057
74058static void
74059UA_DataValueMemoryStoreItem_clear(UA_DataValueMemoryStoreItem* item) {
74060 UA_DateTime_clear(p: &item->timestamp);
74061 UA_DataValue_clear(p: &item->value);
74062}
74063
74064typedef struct {
74065 UA_NodeId nodeId;
74066 UA_DataValueMemoryStoreItem **dataStore;
74067 size_t storeEnd;
74068 size_t storeSize;
74069} UA_NodeIdStoreContextItem_backend_memory;
74070
74071static void
74072UA_NodeIdStoreContextItem_clear(UA_NodeIdStoreContextItem_backend_memory* item) {
74073 UA_NodeId_clear(p: &item->nodeId);
74074 for (size_t i = 0; i < item->storeEnd; ++i) {
74075 UA_DataValueMemoryStoreItem_clear(item: item->dataStore[i]);
74076 UA_free(ptr: item->dataStore[i]);
74077 }
74078 UA_free(ptr: item->dataStore);
74079}
74080
74081typedef struct {
74082 UA_NodeIdStoreContextItem_backend_memory *dataStore;
74083 size_t storeEnd;
74084 size_t storeSize;
74085 size_t initialStoreSize;
74086} UA_MemoryStoreContext;
74087
74088static void
74089UA_MemoryStoreContext_clear(UA_MemoryStoreContext* ctx) {
74090 for (size_t i = 0; i < ctx->storeEnd; ++i) {
74091 UA_NodeIdStoreContextItem_clear(item: &ctx->dataStore[i]);
74092 }
74093 UA_free(ptr: ctx->dataStore);
74094 memset(s: ctx, c: 0, n: sizeof(UA_MemoryStoreContext));
74095}
74096
74097static UA_NodeIdStoreContextItem_backend_memory *
74098getNewNodeIdContext_backend_memory(UA_MemoryStoreContext* context,
74099 UA_Server *server,
74100 const UA_NodeId *nodeId) {
74101 UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext*)context;
74102 if (ctx->storeEnd >= ctx->storeSize) {
74103 size_t newStoreSize = ctx->storeSize * 2;
74104 if (newStoreSize == 0)
74105 return NULL;
74106 ctx->dataStore = (UA_NodeIdStoreContextItem_backend_memory*)UA_realloc(ptr: ctx->dataStore, size: (newStoreSize * sizeof(UA_NodeIdStoreContextItem_backend_memory)));
74107 if (!ctx->dataStore) {
74108 ctx->storeSize = 0;
74109 return NULL;
74110 }
74111 ctx->storeSize = newStoreSize;
74112 }
74113 UA_NodeIdStoreContextItem_backend_memory *item = &ctx->dataStore[ctx->storeEnd];
74114 UA_NodeId_copy(src: nodeId, dst: &item->nodeId);
74115 UA_DataValueMemoryStoreItem ** store = (UA_DataValueMemoryStoreItem **)UA_calloc(nmemb: ctx->initialStoreSize, size: sizeof(UA_DataValueMemoryStoreItem*));
74116 if (!store) {
74117 UA_NodeIdStoreContextItem_clear(item);
74118 return NULL;
74119 }
74120 item->dataStore = store;
74121 item->storeSize = ctx->initialStoreSize;
74122 item->storeEnd = 0;
74123 ++ctx->storeEnd;
74124 return item;
74125}
74126
74127static UA_NodeIdStoreContextItem_backend_memory *
74128getNodeIdStoreContextItem_backend_memory(UA_MemoryStoreContext* context,
74129 UA_Server *server,
74130 const UA_NodeId *nodeId)
74131{
74132 for (size_t i = 0; i < context->storeEnd; ++i) {
74133 if (UA_NodeId_equal(n1: nodeId, n2: &context->dataStore[i].nodeId)) {
74134 return &context->dataStore[i];
74135 }
74136 }
74137 return getNewNodeIdContext_backend_memory(context, server, nodeId);
74138}
74139
74140static UA_Boolean
74141binarySearch_backend_memory(const UA_NodeIdStoreContextItem_backend_memory* item,
74142 const UA_DateTime timestamp,
74143 size_t *index) {
74144 if (item->storeEnd == 0) {
74145 *index = item->storeEnd;
74146 return false;
74147 }
74148 size_t min = 0;
74149 size_t max = item->storeEnd - 1;
74150 while (min <= max) {
74151 *index = (min + max) / 2;
74152 if (item->dataStore[*index]->timestamp == timestamp) {
74153 return true;
74154 } else if (item->dataStore[*index]->timestamp < timestamp) {
74155 if (*index == item->storeEnd - 1) {
74156 *index = item->storeEnd;
74157 return false;
74158 }
74159 min = *index + 1;
74160 } else {
74161 if (*index == 0)
74162 return false;
74163 max = *index - 1;
74164 }
74165 }
74166 *index = min;
74167 return false;
74168
74169}
74170
74171static size_t
74172resultSize_backend_memory(UA_Server *server,
74173 void *context,
74174 const UA_NodeId *sessionId,
74175 void *sessionContext,
74176 const UA_NodeId * nodeId,
74177 size_t startIndex,
74178 size_t endIndex) {
74179 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74180 if (item->storeEnd == 0
74181 || startIndex == item->storeEnd
74182 || endIndex == item->storeEnd)
74183 return 0;
74184 return endIndex - startIndex + 1;
74185}
74186
74187static size_t
74188getDateTimeMatch_backend_memory(UA_Server *server,
74189 void *context,
74190 const UA_NodeId *sessionId,
74191 void *sessionContext,
74192 const UA_NodeId * nodeId,
74193 const UA_DateTime timestamp,
74194 const MatchStrategy strategy) {
74195 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74196 size_t current;
74197 UA_Boolean retval = binarySearch_backend_memory(item, timestamp, index: &current);
74198
74199 if ((strategy == MATCH_EQUAL
74200 || strategy == MATCH_EQUAL_OR_AFTER
74201 || strategy == MATCH_EQUAL_OR_BEFORE)
74202 && retval)
74203 return current;
74204 switch (strategy) {
74205 case MATCH_AFTER:
74206 if (retval)
74207 return current+1;
74208 return current;
74209 case MATCH_EQUAL_OR_AFTER:
74210 return current;
74211 case MATCH_EQUAL_OR_BEFORE:
74212 // retval == true aka "equal" is handled before
74213 // Fall through if !retval
74214 case MATCH_BEFORE:
74215 if (current > 0)
74216 return current-1;
74217 else
74218 return item->storeEnd;
74219 default:
74220 break;
74221 }
74222 return item->storeEnd;
74223}
74224
74225
74226static UA_StatusCode
74227serverSetHistoryData_backend_memory(UA_Server *server,
74228 void *context,
74229 const UA_NodeId *sessionId,
74230 void *sessionContext,
74231 const UA_NodeId * nodeId,
74232 UA_Boolean historizing,
74233 const UA_DataValue *value)
74234{
74235 UA_NodeIdStoreContextItem_backend_memory *item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74236
74237 if (item->storeEnd >= item->storeSize) {
74238 size_t newStoreSize = item->storeSize == 0 ? INITIAL_MEMORY_STORE_SIZE : item->storeSize * 2;
74239 item->dataStore = (UA_DataValueMemoryStoreItem **)UA_realloc(ptr: item->dataStore, size: (newStoreSize * sizeof(UA_DataValueMemoryStoreItem*)));
74240 if (!item->dataStore) {
74241 item->storeSize = 0;
74242 return UA_STATUSCODE_BADOUTOFMEMORY;
74243 }
74244 item->storeSize = newStoreSize;
74245 }
74246 UA_DateTime timestamp = 0;
74247 if (value->hasSourceTimestamp) {
74248 timestamp = value->sourceTimestamp;
74249 } else if (value->hasServerTimestamp) {
74250 timestamp = value->serverTimestamp;
74251 } else {
74252 timestamp = UA_DateTime_now();
74253 }
74254 UA_DataValueMemoryStoreItem *newItem = (UA_DataValueMemoryStoreItem *)UA_calloc(nmemb: 1, size: sizeof(UA_DataValueMemoryStoreItem));
74255 newItem->timestamp = timestamp;
74256 UA_DataValue_copy(src: value, dst: &newItem->value);
74257 size_t index = getDateTimeMatch_backend_memory(server,
74258 context,
74259 NULL,
74260 NULL,
74261 nodeId,
74262 timestamp,
74263 strategy: MATCH_EQUAL_OR_AFTER);
74264 if (item->storeEnd > 0 && index < item->storeEnd) {
74265 memmove(dest: &item->dataStore[index+1], src: &item->dataStore[index], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index));
74266 }
74267 item->dataStore[index] = newItem;
74268 ++item->storeEnd;
74269 return UA_STATUSCODE_GOOD;
74270}
74271
74272static void
74273UA_MemoryStoreContext_delete(UA_MemoryStoreContext* ctx) {
74274 UA_MemoryStoreContext_clear(ctx);
74275 UA_free(ptr: ctx);
74276}
74277
74278static size_t
74279getEnd_backend_memory(UA_Server *server,
74280 void *context,
74281 const UA_NodeId *sessionId,
74282 void *sessionContext,
74283 const UA_NodeId * nodeId) {
74284 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74285 return item->storeEnd;
74286}
74287
74288static size_t
74289lastIndex_backend_memory(UA_Server *server,
74290 void *context,
74291 const UA_NodeId *sessionId,
74292 void *sessionContext,
74293 const UA_NodeId * nodeId) {
74294 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74295 if (item->storeEnd == 0)
74296 return 0;
74297 return item->storeEnd - 1;
74298}
74299
74300static size_t
74301firstIndex_backend_memory(UA_Server *server,
74302 void *context,
74303 const UA_NodeId *sessionId,
74304 void *sessionContext,
74305 const UA_NodeId * nodeId) {
74306 return 0;
74307}
74308
74309static UA_Boolean
74310boundSupported_backend_memory(UA_Server *server,
74311 void *context,
74312 const UA_NodeId *sessionId,
74313 void *sessionContext,
74314 const UA_NodeId * nodeId) {
74315 return true;
74316}
74317
74318static UA_Boolean
74319timestampsToReturnSupported_backend_memory(UA_Server *server,
74320 void *context,
74321 const UA_NodeId *sessionId,
74322 void *sessionContext,
74323 const UA_NodeId *nodeId,
74324 const UA_TimestampsToReturn timestampsToReturn) {
74325 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74326 if (item->storeEnd == 0) {
74327 return true;
74328 }
74329 if (timestampsToReturn == UA_TIMESTAMPSTORETURN_NEITHER
74330 || timestampsToReturn == UA_TIMESTAMPSTORETURN_INVALID
74331 || (timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER
74332 && !item->dataStore[0]->value.hasServerTimestamp)
74333 || (timestampsToReturn == UA_TIMESTAMPSTORETURN_SOURCE
74334 && !item->dataStore[0]->value.hasSourceTimestamp)
74335 || (timestampsToReturn == UA_TIMESTAMPSTORETURN_BOTH
74336 && !(item->dataStore[0]->value.hasSourceTimestamp
74337 && item->dataStore[0]->value.hasServerTimestamp))) {
74338 return false;
74339 }
74340 return true;
74341}
74342
74343static const UA_DataValue*
74344getDataValue_backend_memory(UA_Server *server,
74345 void *context,
74346 const UA_NodeId *sessionId,
74347 void *sessionContext,
74348 const UA_NodeId * nodeId, size_t index) {
74349 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74350 return &item->dataStore[index]->value;
74351}
74352
74353static UA_StatusCode
74354UA_DataValue_backend_copyRange(const UA_DataValue *src, UA_DataValue *dst,
74355 const UA_NumericRange range)
74356{
74357 memcpy(dest: dst, src: src, n: sizeof(UA_DataValue));
74358 if (src->hasValue)
74359 return UA_Variant_copyRange(src: &src->value, dst: &dst->value, range);
74360 return UA_STATUSCODE_BADDATAUNAVAILABLE;
74361}
74362
74363static UA_StatusCode
74364copyDataValues_backend_memory(UA_Server *server,
74365 void *context,
74366 const UA_NodeId *sessionId,
74367 void *sessionContext,
74368 const UA_NodeId * nodeId,
74369 size_t startIndex,
74370 size_t endIndex,
74371 UA_Boolean reverse,
74372 size_t maxValues,
74373 UA_NumericRange range,
74374 UA_Boolean releaseContinuationPoints,
74375 const UA_ByteString *continuationPoint,
74376 UA_ByteString *outContinuationPoint,
74377 size_t * providedValues,
74378 UA_DataValue * values)
74379{
74380 size_t skip = 0;
74381 if (continuationPoint->length > 0) {
74382 if (continuationPoint->length == sizeof(size_t)) {
74383 skip = *((size_t*)(continuationPoint->data));
74384 } else {
74385 return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
74386 }
74387 }
74388 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74389 size_t index = startIndex;
74390 size_t counter = 0;
74391 size_t skipedValues = 0;
74392 if (reverse) {
74393 while (index >= endIndex && index < item->storeEnd && counter < maxValues) {
74394 if (skipedValues++ >= skip) {
74395 if (range.dimensionsSize > 0) {
74396 UA_DataValue_backend_copyRange(src: &item->dataStore[index]->value, dst: &values[counter], range);
74397 } else {
74398 UA_DataValue_copy(src: &item->dataStore[index]->value, dst: &values[counter]);
74399 }
74400 ++counter;
74401 }
74402 --index;
74403 }
74404 } else {
74405 while (index <= endIndex && counter < maxValues) {
74406 if (skipedValues++ >= skip) {
74407 if (range.dimensionsSize > 0) {
74408 UA_DataValue_backend_copyRange(src: &item->dataStore[index]->value, dst: &values[counter], range);
74409 } else {
74410 UA_DataValue_copy(src: &item->dataStore[index]->value, dst: &values[counter]);
74411 }
74412 ++counter;
74413 }
74414 ++index;
74415 }
74416 }
74417
74418 if (providedValues)
74419 *providedValues = counter;
74420
74421 if ((!reverse && (endIndex-startIndex-skip+1) > counter) || (reverse && (startIndex-endIndex-skip+1) > counter)) {
74422 outContinuationPoint->length = sizeof(size_t);
74423 size_t t = sizeof(size_t);
74424 outContinuationPoint->data = (UA_Byte*)UA_malloc(size: t);
74425 *((size_t*)(outContinuationPoint->data)) = skip + counter;
74426 }
74427
74428 return UA_STATUSCODE_GOOD;
74429}
74430
74431static UA_StatusCode
74432insertDataValue_backend_memory(UA_Server *server,
74433 void *hdbContext,
74434 const UA_NodeId *sessionId,
74435 void *sessionContext,
74436 const UA_NodeId *nodeId,
74437 const UA_DataValue *value)
74438{
74439 if (!value->hasSourceTimestamp && !value->hasServerTimestamp)
74440 return UA_STATUSCODE_BADINVALIDTIMESTAMP;
74441 const UA_DateTime timestamp = value->hasSourceTimestamp ? value->sourceTimestamp : value->serverTimestamp;
74442 UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId);
74443
74444 size_t index = getDateTimeMatch_backend_memory(server,
74445 context: hdbContext,
74446 sessionId,
74447 sessionContext,
74448 nodeId,
74449 timestamp,
74450 strategy: MATCH_EQUAL_OR_AFTER);
74451 if (item->storeEnd != index && item->dataStore[index]->timestamp == timestamp)
74452 return UA_STATUSCODE_BADENTRYEXISTS;
74453
74454 if (item->storeEnd >= item->storeSize) {
74455 size_t newStoreSize = item->storeSize == 0 ? INITIAL_MEMORY_STORE_SIZE : item->storeSize * 2;
74456 item->dataStore = (UA_DataValueMemoryStoreItem **)UA_realloc(ptr: item->dataStore, size: (newStoreSize * sizeof(UA_DataValueMemoryStoreItem*)));
74457 if (!item->dataStore) {
74458 item->storeSize = 0;
74459 return UA_STATUSCODE_BADOUTOFMEMORY;
74460 }
74461 item->storeSize = newStoreSize;
74462 }
74463 UA_DataValueMemoryStoreItem *newItem = (UA_DataValueMemoryStoreItem *)UA_calloc(nmemb: 1, size: sizeof(UA_DataValueMemoryStoreItem));
74464 newItem->timestamp = timestamp;
74465 UA_DataValue_copy(src: value, dst: &newItem->value);
74466 if (item->storeEnd > 0 && index < item->storeEnd) {
74467 memmove(dest: &item->dataStore[index+1], src: &item->dataStore[index], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index));
74468 }
74469 item->dataStore[index] = newItem;
74470 ++item->storeEnd;
74471 return UA_STATUSCODE_GOOD;
74472}
74473
74474static UA_StatusCode
74475replaceDataValue_backend_memory(UA_Server *server,
74476 void *hdbContext,
74477 const UA_NodeId *sessionId,
74478 void *sessionContext,
74479 const UA_NodeId *nodeId,
74480 const UA_DataValue *value)
74481{
74482 if (!value->hasSourceTimestamp && !value->hasServerTimestamp)
74483 return UA_STATUSCODE_BADINVALIDTIMESTAMP;
74484 const UA_DateTime timestamp = value->hasSourceTimestamp ? value->sourceTimestamp : value->serverTimestamp;
74485 UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId);
74486
74487 size_t index = getDateTimeMatch_backend_memory(server,
74488 context: hdbContext,
74489 sessionId,
74490 sessionContext,
74491 nodeId,
74492 timestamp,
74493 strategy: MATCH_EQUAL);
74494 if (index == item->storeEnd)
74495 return UA_STATUSCODE_BADNOENTRYEXISTS;
74496 UA_DataValue_clear(p: &item->dataStore[index]->value);
74497 UA_DataValue_copy(src: value, dst: &item->dataStore[index]->value);
74498 return UA_STATUSCODE_GOOD;
74499}
74500
74501static UA_StatusCode
74502updateDataValue_backend_memory(UA_Server *server,
74503 void *hdbContext,
74504 const UA_NodeId *sessionId,
74505 void *sessionContext,
74506 const UA_NodeId *nodeId,
74507 const UA_DataValue *value)
74508{
74509 // we first try to replace, because it is cheap
74510 UA_StatusCode ret = replaceDataValue_backend_memory(server,
74511 hdbContext,
74512 sessionId,
74513 sessionContext,
74514 nodeId,
74515 value);
74516 if (ret == UA_STATUSCODE_GOOD)
74517 return UA_STATUSCODE_GOODENTRYREPLACED;
74518
74519 ret = insertDataValue_backend_memory(server,
74520 hdbContext,
74521 sessionId,
74522 sessionContext,
74523 nodeId,
74524 value);
74525 if (ret == UA_STATUSCODE_GOOD)
74526 return UA_STATUSCODE_GOODENTRYINSERTED;
74527
74528 return ret;
74529}
74530
74531static UA_StatusCode
74532removeDataValue_backend_memory(UA_Server *server,
74533 void *hdbContext,
74534 const UA_NodeId *sessionId,
74535 void *sessionContext,
74536 const UA_NodeId *nodeId,
74537 UA_DateTime startTimestamp,
74538 UA_DateTime endTimestamp)
74539{
74540 UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId);
74541 size_t storeEnd = item->storeEnd;
74542 // The first index which will be deleted
74543 size_t index1;
74544 // the first index which is not deleted
74545 size_t index2;
74546 if (startTimestamp > endTimestamp) {
74547 return UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED;
74548 }
74549 if (startTimestamp == endTimestamp) {
74550 index1 = getDateTimeMatch_backend_memory(server,
74551 context: hdbContext,
74552 sessionId,
74553 sessionContext,
74554 nodeId,
74555 timestamp: startTimestamp,
74556 strategy: MATCH_EQUAL);
74557 if (index1 == storeEnd)
74558 return UA_STATUSCODE_BADNODATA;
74559 index2 = index1 + 1;
74560 } else {
74561 index1 = getDateTimeMatch_backend_memory(server,
74562 context: hdbContext,
74563 sessionId,
74564 sessionContext,
74565 nodeId,
74566 timestamp: startTimestamp,
74567 strategy: MATCH_EQUAL_OR_AFTER);
74568 index2 = getDateTimeMatch_backend_memory(server,
74569 context: hdbContext,
74570 sessionId,
74571 sessionContext,
74572 nodeId,
74573 timestamp: endTimestamp,
74574 strategy: MATCH_BEFORE);
74575 if (index2 == storeEnd || index1 == storeEnd || index1 > index2 )
74576 return UA_STATUSCODE_BADNODATA;
74577 ++index2;
74578 }
74579#ifndef __clang_analyzer__
74580 for (size_t i = index1; i < index2; ++i) {
74581 UA_DataValueMemoryStoreItem_clear(item: item->dataStore[i]);
74582 UA_free(ptr: item->dataStore[i]);
74583 }
74584 memmove(dest: &item->dataStore[index1], src: &item->dataStore[index2], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index2));
74585 item->storeEnd -= index2 - index1;
74586#else
74587 (void)index1;
74588 (void)index2;
74589#endif
74590 return UA_STATUSCODE_GOOD;
74591}
74592
74593static void
74594deleteMembers_backend_memory(UA_HistoryDataBackend *backend)
74595{
74596 if (backend == NULL || backend->context == NULL)
74597 return;
74598 UA_MemoryStoreContext_clear(ctx: (UA_MemoryStoreContext*)backend->context);
74599 UA_free(ptr: backend->context);
74600}
74601
74602
74603
74604UA_HistoryDataBackend
74605UA_HistoryDataBackend_Memory(size_t initialNodeIdStoreSize, size_t initialDataStoreSize) {
74606 if (initialNodeIdStoreSize == 0)
74607 initialNodeIdStoreSize = 1;
74608 if (initialDataStoreSize == 0)
74609 initialDataStoreSize = 1;
74610 UA_HistoryDataBackend result;
74611 memset(s: &result, c: 0, n: sizeof(UA_HistoryDataBackend));
74612 UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext *)UA_calloc(nmemb: 1, size: sizeof(UA_MemoryStoreContext));
74613 if (!ctx)
74614 return result;
74615 ctx->dataStore = (UA_NodeIdStoreContextItem_backend_memory*)UA_calloc(nmemb: initialNodeIdStoreSize, size: sizeof(UA_NodeIdStoreContextItem_backend_memory));
74616 ctx->initialStoreSize = initialDataStoreSize;
74617 ctx->storeSize = initialNodeIdStoreSize;
74618 ctx->storeEnd = 0;
74619 result.serverSetHistoryData = &serverSetHistoryData_backend_memory;
74620 result.resultSize = &resultSize_backend_memory;
74621 result.getEnd = &getEnd_backend_memory;
74622 result.lastIndex = &lastIndex_backend_memory;
74623 result.firstIndex = &firstIndex_backend_memory;
74624 result.getDateTimeMatch = &getDateTimeMatch_backend_memory;
74625 result.copyDataValues = &copyDataValues_backend_memory;
74626 result.getDataValue = &getDataValue_backend_memory;
74627 result.boundSupported = &boundSupported_backend_memory;
74628 result.timestampsToReturnSupported = &timestampsToReturnSupported_backend_memory;
74629 result.insertDataValue = &insertDataValue_backend_memory;
74630 result.updateDataValue = &updateDataValue_backend_memory;
74631 result.replaceDataValue = &replaceDataValue_backend_memory;
74632 result.removeDataValue = &removeDataValue_backend_memory;
74633 result.deleteMembers = &deleteMembers_backend_memory;
74634 result.getHistoryData = NULL;
74635 result.context = ctx;
74636 return result;
74637}
74638
74639void
74640UA_HistoryDataBackend_Memory_clear(UA_HistoryDataBackend *backend)
74641{
74642 UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext*)backend->context;
74643 UA_MemoryStoreContext_delete(ctx);
74644 memset(s: backend, c: 0, n: sizeof(UA_HistoryDataBackend));
74645}
74646
74647/**** amalgamated original file "/plugins/historydata/ua_history_data_gathering_default.c" ****/
74648
74649/* This Source Code Form is subject to the terms of the Mozilla Public
74650 * License, v. 2.0. If a copy of the MPL was not distributed with this
74651 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
74652 *
74653 * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler)
74654 */
74655
74656
74657#include <string.h>
74658
74659typedef struct {
74660 UA_NodeId nodeId;
74661 UA_HistorizingNodeIdSettings setting;
74662 UA_MonitoredItemCreateResult monitoredResult;
74663} UA_NodeIdStoreContextItem_gathering_default;
74664
74665typedef struct {
74666 UA_NodeIdStoreContextItem_gathering_default *dataStore;
74667 size_t storeEnd;
74668 size_t storeSize;
74669} UA_NodeIdStoreContext;
74670
74671static void
74672dataChangeCallback_gathering_default(UA_Server *server,
74673 UA_UInt32 monitoredItemId,
74674 void *monitoredItemContext,
74675 const UA_NodeId *nodeId,
74676 void *nodeContext,
74677 UA_UInt32 attributeId,
74678 const UA_DataValue *value)
74679{
74680 UA_NodeIdStoreContextItem_gathering_default *context = (UA_NodeIdStoreContextItem_gathering_default*)monitoredItemContext;
74681 context->setting.historizingBackend.serverSetHistoryData(server,
74682 context->setting.historizingBackend.context,
74683 NULL,
74684 NULL,
74685 nodeId,
74686 UA_TRUE,
74687 value);
74688}
74689
74690static UA_NodeIdStoreContextItem_gathering_default*
74691getNodeIdStoreContextItem_gathering_default(UA_NodeIdStoreContext *context,
74692 const UA_NodeId *nodeId)
74693{
74694 for (size_t i = 0; i < context->storeEnd; ++i) {
74695 if (UA_NodeId_equal(n1: &context->dataStore[i].nodeId, n2: nodeId)) {
74696 return &context->dataStore[i];
74697 }
74698 }
74699 return NULL;
74700}
74701
74702static UA_StatusCode
74703startPoll(UA_Server *server, UA_NodeIdStoreContextItem_gathering_default *item)
74704{
74705 UA_MonitoredItemCreateRequest monitorRequest =
74706 UA_MonitoredItemCreateRequest_default(nodeId: item->nodeId);
74707 monitorRequest.requestedParameters.samplingInterval = (double)item->setting.pollingInterval;
74708 monitorRequest.monitoringMode = UA_MONITORINGMODE_REPORTING;
74709 item->monitoredResult =
74710 UA_Server_createDataChangeMonitoredItem(server,
74711 timestampsToReturn: UA_TIMESTAMPSTORETURN_BOTH,
74712 item: monitorRequest,
74713 monitoredItemContext: item,
74714 callback: &dataChangeCallback_gathering_default);
74715 return item->monitoredResult.statusCode;
74716}
74717
74718static UA_StatusCode
74719stopPoll(UA_Server *server, UA_NodeIdStoreContextItem_gathering_default *item)
74720{
74721 UA_StatusCode retval = UA_Server_deleteMonitoredItem(server, monitoredItemId: item->monitoredResult.monitoredItemId);
74722 UA_MonitoredItemCreateResult_init(p: &item->monitoredResult);
74723 return retval;
74724}
74725
74726static UA_StatusCode
74727stopPoll_gathering_default(UA_Server *server,
74728 void *context,
74729 const UA_NodeId *nodeId)
74730{
74731 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context;
74732 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
74733 if (!item) {
74734 return UA_STATUSCODE_BADNODEIDUNKNOWN;
74735 }
74736 if (item->setting.historizingUpdateStrategy != UA_HISTORIZINGUPDATESTRATEGY_POLL)
74737 return UA_STATUSCODE_BADNODEIDINVALID;
74738 if (item->monitoredResult.monitoredItemId == 0)
74739 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
74740 return stopPoll(server, item);
74741}
74742
74743static UA_StatusCode
74744startPoll_gathering_default(UA_Server *server,
74745 void *context,
74746 const UA_NodeId *nodeId)
74747{
74748 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context;
74749 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
74750 if (!item) {
74751 return UA_STATUSCODE_BADNODEIDUNKNOWN;
74752 }
74753 if (item->setting.historizingUpdateStrategy != UA_HISTORIZINGUPDATESTRATEGY_POLL)
74754 return UA_STATUSCODE_BADNODEIDINVALID;
74755 if (item->monitoredResult.monitoredItemId > 0)
74756 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
74757 return startPoll(server, item);
74758}
74759
74760static UA_StatusCode
74761registerNodeId_gathering_default(UA_Server *server,
74762 void *context,
74763 const UA_NodeId *nodeId,
74764 const UA_HistorizingNodeIdSettings setting)
74765{
74766 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
74767 if (getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId)) {
74768 return UA_STATUSCODE_BADNODEIDEXISTS;
74769 }
74770 if (ctx->storeEnd >= ctx->storeSize) {
74771 size_t newStoreSize = ctx->storeSize * 2;
74772 ctx->dataStore = (UA_NodeIdStoreContextItem_gathering_default*)UA_realloc(ptr: ctx->dataStore, size: (newStoreSize * sizeof(UA_NodeIdStoreContextItem_gathering_default)));
74773 if (!ctx->dataStore) {
74774 ctx->storeSize = 0;
74775 return UA_STATUSCODE_BADOUTOFMEMORY;
74776 }
74777 memset(s: &ctx->dataStore[ctx->storeSize], c: 0, n: (newStoreSize - ctx->storeSize) * sizeof(UA_NodeIdStoreContextItem_gathering_default));
74778 ctx->storeSize = newStoreSize;
74779 }
74780 UA_NodeId_copy(src: nodeId, dst: &ctx->dataStore[ctx->storeEnd].nodeId);
74781 size_t current = ctx->storeEnd;
74782 ctx->dataStore[current].setting = setting;
74783 ++ctx->storeEnd;
74784 return UA_STATUSCODE_GOOD;
74785}
74786
74787static const UA_HistorizingNodeIdSettings*
74788getHistorizingSetting_gathering_default(UA_Server *server,
74789 void *context,
74790 const UA_NodeId *nodeId)
74791{
74792 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
74793 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
74794 if (item) {
74795 return &item->setting;
74796 }
74797 return NULL;
74798}
74799
74800static void
74801deleteMembers_gathering_default(UA_HistoryDataGathering *gathering)
74802{
74803 if (gathering == NULL || gathering->context == NULL)
74804 return;
74805 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)gathering->context;
74806 for (size_t i = 0; i < ctx->storeEnd; ++i) {
74807 UA_NodeId_clear(p: &ctx->dataStore[i].nodeId);
74808 // There is still a monitored item present for this gathering
74809 // You need to remove it with UA_Server_deleteMonitoredItem
74810 UA_assert(ctx->dataStore[i].monitoredResult.monitoredItemId == 0);
74811 }
74812 UA_free(ptr: ctx->dataStore);
74813 UA_free(ptr: gathering->context);
74814}
74815
74816static UA_Boolean
74817updateNodeIdSetting_gathering_default(UA_Server *server,
74818 void *context,
74819 const UA_NodeId *nodeId,
74820 const UA_HistorizingNodeIdSettings setting)
74821{
74822 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
74823 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
74824 if (!item) {
74825 return false;
74826 }
74827 stopPoll_gathering_default(server, context, nodeId);
74828 item->setting = setting;
74829 return true;
74830}
74831
74832static void
74833setValue_gathering_default(UA_Server *server,
74834 void *context,
74835 const UA_NodeId *sessionId,
74836 void *sessionContext,
74837 const UA_NodeId *nodeId,
74838 UA_Boolean historizing,
74839 const UA_DataValue *value)
74840{
74841 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
74842 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
74843 if (!item) {
74844 return;
74845 }
74846 if (item->setting.historizingUpdateStrategy == UA_HISTORIZINGUPDATESTRATEGY_VALUESET) {
74847 item->setting.historizingBackend.serverSetHistoryData(server,
74848 item->setting.historizingBackend.context,
74849 sessionId,
74850 sessionContext,
74851 nodeId,
74852 historizing,
74853 value);
74854 }
74855}
74856
74857UA_HistoryDataGathering
74858UA_HistoryDataGathering_Default(size_t initialNodeIdStoreSize)
74859{
74860 UA_HistoryDataGathering gathering;
74861 memset(s: &gathering, c: 0, n: sizeof(UA_HistoryDataGathering));
74862 gathering.setValue = &setValue_gathering_default;
74863 gathering.getHistorizingSetting = &getHistorizingSetting_gathering_default;
74864 gathering.registerNodeId = &registerNodeId_gathering_default;
74865 gathering.startPoll = &startPoll_gathering_default;
74866 gathering.stopPoll = &stopPoll_gathering_default;
74867 gathering.deleteMembers = &deleteMembers_gathering_default;
74868 gathering.updateNodeIdSetting = &updateNodeIdSetting_gathering_default;
74869 UA_NodeIdStoreContext *context = (UA_NodeIdStoreContext*)UA_calloc(nmemb: 1, size: sizeof(UA_NodeIdStoreContext));
74870 context->storeEnd = 0;
74871 context->storeSize = initialNodeIdStoreSize;
74872 context->dataStore = (UA_NodeIdStoreContextItem_gathering_default*)UA_calloc(nmemb: initialNodeIdStoreSize, size: sizeof(UA_NodeIdStoreContextItem_gathering_default));
74873 gathering.context = context;
74874 return gathering;
74875}
74876
74877/**** amalgamated original file "/plugins/historydata/ua_history_database_default.c" ****/
74878
74879/* This Source Code Form is subject to the terms of the Mozilla Public
74880 * License, v. 2.0. If a copy of the MPL was not distributed with this
74881 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
74882 *
74883 * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler)
74884 */
74885
74886
74887#include <limits.h>
74888
74889typedef struct {
74890 UA_HistoryDataGathering gathering;
74891} UA_HistoryDatabaseContext_default;
74892
74893static size_t
74894getResultSize_service_default(const UA_HistoryDataBackend* backend,
74895 UA_Server *server,
74896 const UA_NodeId *sessionId,
74897 void* sessionContext,
74898 const UA_NodeId *nodeId,
74899 UA_DateTime start,
74900 UA_DateTime end,
74901 UA_UInt32 numValuesPerNode,
74902 UA_Boolean returnBounds,
74903 size_t *startIndex,
74904 size_t *endIndex,
74905 UA_Boolean *addFirst,
74906 UA_Boolean *addLast,
74907 UA_Boolean *reverse)
74908{
74909 size_t storeEnd = backend->getEnd(server, backend->context, sessionId, sessionContext, nodeId);
74910 size_t firstIndex = backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId);
74911 size_t lastIndex = backend->lastIndex(server, backend->context, sessionId, sessionContext, nodeId);
74912 *startIndex = storeEnd;
74913 *endIndex = storeEnd;
74914 *addFirst = false;
74915 *addLast = false;
74916 if (end == LLONG_MIN) {
74917 *reverse = false;
74918 } else if (start == LLONG_MIN) {
74919 *reverse = true;
74920 } else {
74921 *reverse = end < start;
74922 }
74923 UA_Boolean equal = start == end;
74924 size_t size = 0;
74925 if (lastIndex != storeEnd) {
74926 if (equal) {
74927 if (returnBounds) {
74928 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE);
74929 if (*startIndex == storeEnd) {
74930 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER);
74931 *addFirst = true;
74932 }
74933 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER);
74934 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex);
74935 } else {
74936 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL);
74937 *endIndex = *startIndex;
74938 if (*startIndex == storeEnd)
74939 size = 0;
74940 else
74941 size = 1;
74942 }
74943 } else if (start == LLONG_MIN) {
74944 *endIndex = firstIndex;
74945 if (returnBounds) {
74946 *addLast = true;
74947 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_AFTER);
74948 if (*startIndex == storeEnd) {
74949 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE);
74950 *addFirst = true;
74951 }
74952 } else {
74953 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE);
74954 }
74955 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *endIndex, *startIndex);
74956 } else if (end == LLONG_MIN) {
74957 *endIndex = lastIndex;
74958 if (returnBounds) {
74959 *addLast = true;
74960 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE);
74961 if (*startIndex == storeEnd) {
74962 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER);
74963 *addFirst = true;
74964 }
74965 } else {
74966 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER);
74967 }
74968 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex);
74969 } else if (*reverse) {
74970 if (returnBounds) {
74971 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER);
74972 if (*startIndex == storeEnd) {
74973 *addFirst = true;
74974 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_BEFORE);
74975 }
74976 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE);
74977 if (*endIndex == storeEnd) {
74978 *addLast = true;
74979 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_AFTER);
74980 }
74981 } else {
74982 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE);
74983 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_AFTER);
74984 }
74985 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *endIndex, *startIndex);
74986 } else {
74987 if (returnBounds) {
74988 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE);
74989 if (*startIndex == storeEnd) {
74990 *addFirst = true;
74991 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER);
74992 }
74993 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_AFTER);
74994 if (*endIndex == storeEnd) {
74995 *addLast = true;
74996 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_BEFORE);
74997 }
74998 } else {
74999 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER);
75000 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_BEFORE);
75001 }
75002 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex);
75003 }
75004 } else if (returnBounds) {
75005 *addLast = true;
75006 *addFirst = true;
75007 }
75008
75009 if (*addLast)
75010 ++size;
75011 if (*addFirst)
75012 ++size;
75013
75014 if (numValuesPerNode > 0 && size > numValuesPerNode) {
75015 size = numValuesPerNode;
75016 *addLast = false;
75017 }
75018 return size;
75019}
75020
75021static UA_StatusCode
75022getHistoryData_service_default(const UA_HistoryDataBackend* backend,
75023 const UA_DateTime start,
75024 const UA_DateTime end,
75025 UA_Server *server,
75026 const UA_NodeId *sessionId,
75027 void *sessionContext,
75028 const UA_NodeId* nodeId,
75029 size_t maxSize,
75030 UA_UInt32 numValuesPerNode,
75031 UA_Boolean returnBounds,
75032 UA_TimestampsToReturn timestampsToReturn,
75033 UA_NumericRange range,
75034 UA_Boolean releaseContinuationPoints,
75035 const UA_ByteString *continuationPoint,
75036 UA_ByteString *outContinuationPoint,
75037 size_t *resultSize,
75038 UA_DataValue ** result)
75039{
75040 size_t skip = 0;
75041 UA_ByteString backendContinuationPoint;
75042 UA_ByteString_init(p: &backendContinuationPoint);
75043 if (continuationPoint->length > 0) {
75044 if (continuationPoint->length >= sizeof(size_t)) {
75045 skip = *((size_t*)(continuationPoint->data));
75046 if (continuationPoint->length > 0) {
75047 backendContinuationPoint.length = continuationPoint->length - sizeof(size_t);
75048 backendContinuationPoint.data = continuationPoint->data + sizeof(size_t);
75049 }
75050 } else {
75051 return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
75052 }
75053 }
75054
75055 size_t storeEnd = backend->getEnd(server, backend->context, sessionId, sessionContext, nodeId);
75056 size_t startIndex;
75057 size_t endIndex;
75058 UA_Boolean addFirst;
75059 UA_Boolean addLast;
75060 UA_Boolean reverse;
75061 size_t _resultSize = getResultSize_service_default(backend,
75062 server,
75063 sessionId,
75064 sessionContext,
75065 nodeId,
75066 start,
75067 end,
75068 numValuesPerNode: numValuesPerNode == 0 ? 0 : numValuesPerNode + (UA_UInt32)skip,
75069 returnBounds,
75070 startIndex: &startIndex,
75071 endIndex: &endIndex,
75072 addFirst: &addFirst,
75073 addLast: &addLast,
75074 reverse: &reverse);
75075 *resultSize = _resultSize - skip;
75076 if (*resultSize > maxSize) {
75077 *resultSize = maxSize;
75078 }
75079 UA_DataValue *outResult= (UA_DataValue*)UA_Array_new(size: *resultSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]);
75080 if (!outResult) {
75081 *resultSize = 0;
75082 return UA_STATUSCODE_BADOUTOFMEMORY;
75083 }
75084 *result = outResult;
75085
75086 size_t counter = 0;
75087 if (addFirst) {
75088 if (skip == 0) {
75089 outResult[counter].hasStatus = true;
75090 outResult[counter].status = UA_STATUSCODE_BADBOUNDNOTFOUND;
75091 outResult[counter].hasSourceTimestamp = true;
75092 if (start == LLONG_MIN) {
75093 outResult[counter].sourceTimestamp = end;
75094 } else {
75095 outResult[counter].sourceTimestamp = start;
75096 }
75097 ++counter;
75098 }
75099 }
75100 UA_ByteString backendOutContinuationPoint;
75101 UA_ByteString_init(p: &backendOutContinuationPoint);
75102 if (endIndex != storeEnd && startIndex != storeEnd) {
75103 size_t retval = 0;
75104
75105 size_t valueSize = *resultSize - counter;
75106 if (valueSize + skip > _resultSize - addFirst - addLast) {
75107 if (skip == 0) {
75108 valueSize = _resultSize - addFirst - addLast;
75109 } else {
75110 valueSize = _resultSize - skip - addLast;
75111 }
75112
75113 }
75114
75115 UA_StatusCode ret = UA_STATUSCODE_GOOD;
75116 if (valueSize > 0)
75117 ret = backend->copyDataValues(server,
75118 backend->context,
75119 sessionId,
75120 sessionContext,
75121 nodeId,
75122 startIndex,
75123 endIndex,
75124 reverse,
75125 valueSize,
75126 range,
75127 releaseContinuationPoints,
75128 &backendContinuationPoint,
75129 &backendOutContinuationPoint,
75130 &retval,
75131 &outResult[counter]);
75132 if (ret != UA_STATUSCODE_GOOD) {
75133 UA_Array_delete(p: outResult, size: *resultSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]);
75134 *result = NULL;
75135 *resultSize = 0;
75136 return ret;
75137 }
75138 counter += retval;
75139 }
75140 if (addLast && counter < *resultSize) {
75141 outResult[counter].hasStatus = true;
75142 outResult[counter].status = UA_STATUSCODE_BADBOUNDNOTFOUND;
75143 outResult[counter].hasSourceTimestamp = true;
75144 if (start == LLONG_MIN && storeEnd != backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId)) {
75145 outResult[counter].sourceTimestamp = backend->getDataValue(server, backend->context, sessionId, sessionContext, nodeId, endIndex)->sourceTimestamp - UA_DATETIME_SEC;
75146 } else if (end == LLONG_MIN && storeEnd != backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId)) {
75147 outResult[counter].sourceTimestamp = backend->getDataValue(server, backend->context, sessionId, sessionContext, nodeId, endIndex)->sourceTimestamp + UA_DATETIME_SEC;
75148 } else {
75149 outResult[counter].sourceTimestamp = end;
75150 }
75151 }
75152 // there are more values
75153 if (skip + *resultSize < _resultSize
75154 // there are not more values for this request, but there are more values in database
75155 || (backendOutContinuationPoint.length > 0
75156 && numValuesPerNode != 0)
75157 // we deliver just one value which is a FIRST/LAST value
75158 || (skip == 0
75159 && addFirst == true
75160 && *resultSize == 1)) {
75161 if(UA_ByteString_allocBuffer(bs: outContinuationPoint, length: backendOutContinuationPoint.length + sizeof(size_t))
75162 != UA_STATUSCODE_GOOD) {
75163 return UA_STATUSCODE_BADOUTOFMEMORY;
75164 }
75165 *((size_t*)(outContinuationPoint->data)) = skip + *resultSize;
75166 if(backendOutContinuationPoint.length > 0)
75167 memcpy(dest: outContinuationPoint->data + sizeof(size_t), src: backendOutContinuationPoint.data, n: backendOutContinuationPoint.length);
75168 }
75169 UA_ByteString_clear(p: &backendOutContinuationPoint);
75170 return UA_STATUSCODE_GOOD;
75171}
75172
75173static void
75174updateData_service_default(UA_Server *server,
75175 void *hdbContext,
75176 const UA_NodeId *sessionId,
75177 void *sessionContext,
75178 const UA_RequestHeader *requestHeader,
75179 const UA_UpdateDataDetails *details,
75180 UA_HistoryUpdateResult *result)
75181{
75182 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdbContext;
75183 UA_Byte accessLevel = 0;
75184 UA_Server_readAccessLevel(server,
75185 nodeId: details->nodeId,
75186 outAccessLevel: &accessLevel);
75187 if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYWRITE)) {
75188 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
75189 return;
75190 }
75191
75192 UA_Boolean historizing = false;
75193 UA_Server_readHistorizing(server,
75194 nodeId: details->nodeId,
75195 outHistorizing: &historizing);
75196 if (!historizing) {
75197 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75198 return;
75199 }
75200 const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting(
75201 server,
75202 ctx->gathering.context,
75203 &details->nodeId);
75204
75205 if (!setting) {
75206 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75207 return;
75208 }
75209
75210 UA_ServerConfig *config = UA_Server_getConfig(server);
75211 result->operationResultsSize = details->updateValuesSize;
75212 result->operationResults = (UA_StatusCode*)UA_Array_new(size: result->operationResultsSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
75213 for (size_t i = 0; i < details->updateValuesSize; ++i) {
75214 if (config->accessControl.allowHistoryUpdateUpdateData &&
75215 !config->accessControl.allowHistoryUpdateUpdateData(server, &config->accessControl, sessionId, sessionContext,
75216 &details->nodeId, details->performInsertReplace,
75217 &details->updateValues[i])) {
75218 result->operationResults[i] = UA_STATUSCODE_BADUSERACCESSDENIED;
75219 continue;
75220 }
75221 switch (details->performInsertReplace) {
75222 case UA_PERFORMUPDATETYPE_INSERT:
75223 if (!setting->historizingBackend.insertDataValue) {
75224 result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75225 continue;
75226 }
75227 result->operationResults[i]
75228 = setting->historizingBackend.insertDataValue(server,
75229 setting->historizingBackend.context,
75230 sessionId,
75231 sessionContext,
75232 &details->nodeId,
75233 &details->updateValues[i]);
75234 continue;
75235 case UA_PERFORMUPDATETYPE_REPLACE:
75236 if (!setting->historizingBackend.replaceDataValue) {
75237 result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75238 continue;
75239 }
75240 result->operationResults[i]
75241 = setting->historizingBackend.replaceDataValue(server,
75242 setting->historizingBackend.context,
75243 sessionId,
75244 sessionContext,
75245 &details->nodeId,
75246 &details->updateValues[i]);
75247 continue;
75248 case UA_PERFORMUPDATETYPE_UPDATE:
75249 if (!setting->historizingBackend.updateDataValue) {
75250 result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75251 continue;
75252 }
75253 result->operationResults[i]
75254 = setting->historizingBackend.updateDataValue(server,
75255 setting->historizingBackend.context,
75256 sessionId,
75257 sessionContext,
75258 &details->nodeId,
75259 &details->updateValues[i]);
75260 continue;
75261 default:
75262 result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75263 continue;
75264 }
75265 }
75266}
75267
75268
75269static void
75270deleteRawModified_service_default(UA_Server *server,
75271 void *hdbContext,
75272 const UA_NodeId *sessionId,
75273 void *sessionContext,
75274 const UA_RequestHeader *requestHeader,
75275 const UA_DeleteRawModifiedDetails *details,
75276 UA_HistoryUpdateResult *result)
75277{
75278 if (details->isDeleteModified) {
75279 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75280 return;
75281 }
75282 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdbContext;
75283 UA_Byte accessLevel = 0;
75284 UA_Server_readAccessLevel(server,
75285 nodeId: details->nodeId,
75286 outAccessLevel: &accessLevel);
75287 if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYWRITE)) {
75288 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
75289 return;
75290 }
75291
75292 UA_Boolean historizing = false;
75293 UA_Server_readHistorizing(server,
75294 nodeId: details->nodeId,
75295 outHistorizing: &historizing);
75296 if (!historizing) {
75297 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75298 return;
75299 }
75300 const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting(
75301 server,
75302 ctx->gathering.context,
75303 &details->nodeId);
75304
75305 if (!setting) {
75306 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75307 return;
75308 }
75309 if (!setting->historizingBackend.removeDataValue) {
75310 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75311 return;
75312 }
75313
75314 UA_ServerConfig *config = UA_Server_getConfig(server);
75315 if (config->accessControl.allowHistoryUpdateDeleteRawModified &&
75316 !config->accessControl.allowHistoryUpdateDeleteRawModified(server,
75317 &config->accessControl, sessionId, sessionContext, &details->nodeId,
75318 details->startTime, details->endTime, details->isDeleteModified)) {
75319 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
75320 return;
75321 }
75322
75323 result->statusCode
75324 = setting->historizingBackend.removeDataValue(server,
75325 setting->historizingBackend.context,
75326 sessionId,
75327 sessionContext,
75328 &details->nodeId,
75329 details->startTime,
75330 details->endTime);
75331}
75332
75333static void
75334readRaw_service_default(UA_Server *server,
75335 void *context,
75336 const UA_NodeId *sessionId,
75337 void *sessionContext,
75338 const UA_RequestHeader *requestHeader,
75339 const UA_ReadRawModifiedDetails *historyReadDetails,
75340 UA_TimestampsToReturn timestampsToReturn,
75341 UA_Boolean releaseContinuationPoints,
75342 size_t nodesToReadSize,
75343 const UA_HistoryReadValueId *nodesToRead,
75344 UA_HistoryReadResponse *response,
75345 UA_HistoryData * const * const historyData)
75346{
75347 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)context;
75348 for (size_t i = 0; i < nodesToReadSize; ++i) {
75349 UA_Byte accessLevel = 0;
75350 UA_Server_readAccessLevel(server,
75351 nodeId: nodesToRead[i].nodeId,
75352 outAccessLevel: &accessLevel);
75353 if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYREAD)) {
75354 response->results[i].statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
75355 continue;
75356 }
75357
75358 UA_Boolean historizing = false;
75359 UA_Server_readHistorizing(server,
75360 nodeId: nodesToRead[i].nodeId,
75361 outHistorizing: &historizing);
75362 if (!historizing) {
75363 response->results[i].statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75364 continue;
75365 }
75366
75367 const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting(
75368 server,
75369 ctx->gathering.context,
75370 &nodesToRead[i].nodeId);
75371
75372 if (!setting) {
75373 response->results[i].statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75374 continue;
75375 }
75376
75377 if (historyReadDetails->returnBounds && !setting->historizingBackend.boundSupported(
75378 server,
75379 setting->historizingBackend.context,
75380 sessionId,
75381 sessionContext,
75382 &nodesToRead[i].nodeId)) {
75383 response->results[i].statusCode = UA_STATUSCODE_BADBOUNDNOTSUPPORTED;
75384 continue;
75385 }
75386
75387 if (!setting->historizingBackend.timestampsToReturnSupported(
75388 server,
75389 setting->historizingBackend.context,
75390 sessionId,
75391 sessionContext,
75392 &nodesToRead[i].nodeId,
75393 timestampsToReturn)) {
75394 response->results[i].statusCode = UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED;
75395 continue;
75396 }
75397
75398 UA_NumericRange range;
75399 range.dimensionsSize = 0;
75400 range.dimensions = NULL;
75401 if (nodesToRead[i].indexRange.length > 0) {
75402 UA_StatusCode rangeParseResult = UA_NumericRange_parse(range: &range, str: nodesToRead[i].indexRange);
75403 if (rangeParseResult != UA_STATUSCODE_GOOD) {
75404 response->results[i].statusCode = rangeParseResult;
75405 continue;
75406 }
75407 }
75408
75409 UA_StatusCode getHistoryDataStatusCode;
75410 if (setting->historizingBackend.getHistoryData) {
75411 getHistoryDataStatusCode = setting->historizingBackend.getHistoryData(
75412 server,
75413 sessionId,
75414 sessionContext,
75415 &setting->historizingBackend,
75416 historyReadDetails->startTime,
75417 historyReadDetails->endTime,
75418 &nodesToRead[i].nodeId,
75419 setting->maxHistoryDataResponseSize,
75420 historyReadDetails->numValuesPerNode,
75421 historyReadDetails->returnBounds,
75422 timestampsToReturn,
75423 range,
75424 releaseContinuationPoints,
75425 &nodesToRead[i].continuationPoint,
75426 &response->results[i].continuationPoint,
75427 historyData[i]);
75428 } else {
75429 getHistoryDataStatusCode = getHistoryData_service_default(
75430 backend: &setting->historizingBackend,
75431 start: historyReadDetails->startTime,
75432 end: historyReadDetails->endTime,
75433 server,
75434 sessionId,
75435 sessionContext,
75436 nodeId: &nodesToRead[i].nodeId,
75437 maxSize: setting->maxHistoryDataResponseSize,
75438 numValuesPerNode: historyReadDetails->numValuesPerNode,
75439 returnBounds: historyReadDetails->returnBounds,
75440 timestampsToReturn,
75441 range,
75442 releaseContinuationPoints,
75443 continuationPoint: &nodesToRead[i].continuationPoint,
75444 outContinuationPoint: &response->results[i].continuationPoint,
75445 resultSize: &historyData[i]->dataValuesSize,
75446 result: &historyData[i]->dataValues);
75447 }
75448 if (getHistoryDataStatusCode != UA_STATUSCODE_GOOD) {
75449 response->results[i].statusCode = getHistoryDataStatusCode;
75450 continue;
75451 }
75452 }
75453 response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
75454 return;
75455}
75456
75457static void
75458setValue_service_default(UA_Server *server,
75459 void *context,
75460 const UA_NodeId *sessionId,
75461 void *sessionContext,
75462 const UA_NodeId *nodeId,
75463 UA_Boolean historizing,
75464 const UA_DataValue *value)
75465{
75466 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)context;
75467 if (ctx->gathering.setValue)
75468 ctx->gathering.setValue(server,
75469 ctx->gathering.context,
75470 sessionId,
75471 sessionContext,
75472 nodeId,
75473 historizing,
75474 value);
75475}
75476
75477static void
75478clear_service_default(UA_HistoryDatabase *hdb)
75479{
75480 if (hdb == NULL || hdb->context == NULL)
75481 return;
75482 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdb->context;
75483 ctx->gathering.deleteMembers(&ctx->gathering);
75484 UA_free(ptr: ctx);
75485}
75486
75487UA_HistoryDatabase
75488UA_HistoryDatabase_default(UA_HistoryDataGathering gathering)
75489{
75490 UA_HistoryDatabase hdb;
75491 memset(s: &hdb, c: 0, n: sizeof(UA_HistoryDatabase));
75492 UA_HistoryDatabaseContext_default *context =
75493 (UA_HistoryDatabaseContext_default*)
75494 UA_calloc(nmemb: 1, size: sizeof(UA_HistoryDatabaseContext_default));
75495 context->gathering = gathering;
75496 hdb.context = context;
75497 hdb.readRaw = &readRaw_service_default;
75498 hdb.setValue = &setValue_service_default;
75499 hdb.updateData = &updateData_service_default;
75500 hdb.deleteRawModified = &deleteRawModified_service_default;
75501 hdb.clear = clear_service_default;
75502 return hdb;
75503}
75504
75505/**** amalgamated original file "/arch/posix/ua_clock.c" ****/
75506
75507/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75508 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75509 *
75510 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
75511 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
75512 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
75513 */
75514
75515#ifdef UA_ARCHITECTURE_POSIX
75516
75517
75518#include <time.h>
75519#include <sys/time.h>
75520
75521#if defined(__APPLE__) || defined(__MACH__)
75522# include <mach/clock.h>
75523# include <mach/mach.h>
75524#endif
75525
75526UA_DateTime UA_DateTime_now(void) {
75527 struct timeval tv;
75528 gettimeofday(tv: &tv, NULL);
75529 return (tv.tv_sec * UA_DATETIME_SEC) + (tv.tv_usec * UA_DATETIME_USEC) + UA_DATETIME_UNIX_EPOCH;
75530}
75531
75532/* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */
75533UA_Int64 UA_DateTime_localTimeUtcOffset(void) {
75534 time_t gmt, rawtime = time(NULL);
75535 struct tm *ptm;
75536 struct tm gbuf;
75537 ptm = gmtime_r(timer: &rawtime, tp: &gbuf);
75538 // Request that mktime() looksup dst in timezone database
75539 ptm->tm_isdst = -1;
75540 gmt = mktime(tp: ptm);
75541 return (UA_Int64) (difftime(time1: rawtime, time0: gmt) * UA_DATETIME_SEC);
75542}
75543
75544UA_DateTime UA_DateTime_nowMonotonic(void) {
75545#if defined(__APPLE__) || defined(__MACH__)
75546 /* OS X does not have clock_gettime, use clock_get_time */
75547 clock_serv_t cclock;
75548 mach_timespec_t mts;
75549 host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
75550 clock_get_time(cclock, &mts);
75551 mach_port_deallocate(mach_task_self(), cclock);
75552 return (mts.tv_sec * UA_DATETIME_SEC) + (mts.tv_nsec / 100);
75553#elif !defined(CLOCK_MONOTONIC_RAW)
75554 struct timespec ts;
75555 clock_gettime(CLOCK_MONOTONIC, &ts);
75556 return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
75557#else
75558 struct timespec ts;
75559 clock_gettime(CLOCK_MONOTONIC_RAW, tp: &ts);
75560 return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
75561#endif
75562}
75563
75564#endif /* UA_ARCHITECTURE_POSIX */
75565
75566/**** amalgamated original file "/arch/posix/ua_architecture_functions.c" ****/
75567
75568/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75569 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75570 *
75571 * Copyright 2018 (c) Jose Cabral, fortiss GmbH
75572 */
75573
75574#ifdef UA_ARCHITECTURE_POSIX
75575
75576
75577/* Global malloc singletons */
75578#ifdef UA_ENABLE_MALLOC_SINGLETON
75579UA_EXPORT UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size) = malloc;
75580UA_EXPORT UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr) = free;
75581UA_EXPORT UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize) = calloc;
75582UA_EXPORT UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size) = realloc;
75583#endif
75584
75585unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
75586 int opts = fcntl(fd: sockfd, F_GETFL);
75587 if(opts < 0 || fcntl(fd: sockfd, F_SETFL, opts & (~O_NONBLOCK)) < 0)
75588 return UA_STATUSCODE_BADINTERNALERROR;
75589 return UA_STATUSCODE_GOOD;
75590}
75591
75592unsigned int UA_socket_set_nonblocking(UA_SOCKET sockfd){
75593 int opts = fcntl(fd: sockfd, F_GETFL);
75594 if(opts < 0 || fcntl(fd: sockfd, F_SETFL, opts | O_NONBLOCK) < 0)
75595 return UA_STATUSCODE_BADINTERNALERROR;
75596 return UA_STATUSCODE_GOOD;
75597}
75598
75599void UA_initialize_architecture_network(void){
75600}
75601
75602void UA_deinitialize_architecture_network(void){
75603}
75604
75605#endif /* UA_ARCHITECTURE_POSIX */
75606
75607/**** amalgamated original file "/arch/win32/ua_clock.c" ****/
75608
75609/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75610 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75611 *
75612 * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
75613 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
75614 * Copyright 2017 (c) Thomas Stalder
75615 */
75616
75617#ifdef UA_ARCHITECTURE_WIN32
75618
75619#ifndef _BSD_SOURCE
75620# define _BSD_SOURCE
75621#endif
75622
75623
75624#include <time.h>
75625/* Backup definition of SLIST_ENTRY on mingw winnt.h */
75626# ifdef SLIST_ENTRY
75627# pragma push_macro("SLIST_ENTRY")
75628# undef SLIST_ENTRY
75629# define POP_SLIST_ENTRY
75630# endif
75631# include <windows.h>
75632/* restore definition */
75633# ifdef POP_SLIST_ENTRY
75634# undef SLIST_ENTRY
75635# undef POP_SLIST_ENTRY
75636# pragma pop_macro("SLIST_ENTRY")
75637# endif
75638
75639UA_DateTime UA_DateTime_now(void) {
75640 /* Windows filetime has the same definition as UA_DateTime */
75641 FILETIME ft;
75642 SYSTEMTIME st;
75643 GetSystemTime(&st);
75644 SystemTimeToFileTime(&st, &ft);
75645 ULARGE_INTEGER ul;
75646 ul.LowPart = ft.dwLowDateTime;
75647 ul.HighPart = ft.dwHighDateTime;
75648 return (UA_DateTime)ul.QuadPart;
75649}
75650
75651/* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */
75652UA_Int64 UA_DateTime_localTimeUtcOffset(void) {
75653 time_t gmt, rawtime = time(NULL);
75654
75655 struct tm ptm;
75656#ifdef __CODEGEARC__
75657 gmtime_s(&rawtime, &ptm);
75658#else
75659 gmtime_s(&ptm, &rawtime);
75660#endif
75661 // Request that mktime() looksup dst in timezone database
75662 ptm.tm_isdst = -1;
75663 gmt = mktime(&ptm);
75664
75665 return (UA_Int64) (difftime(rawtime, gmt) * UA_DATETIME_SEC);
75666}
75667
75668UA_DateTime UA_DateTime_nowMonotonic(void) {
75669 LARGE_INTEGER freq, ticks;
75670 QueryPerformanceFrequency(&freq);
75671 QueryPerformanceCounter(&ticks);
75672 UA_Double ticks2dt = UA_DATETIME_SEC / (UA_Double)freq.QuadPart;
75673 return (UA_DateTime)(ticks.QuadPart * ticks2dt);
75674}
75675
75676#endif /* UA_ARCHITECTURE_WIN32 */
75677
75678/**** amalgamated original file "/arch/win32/ua_architecture_functions.c" ****/
75679
75680/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75681 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75682 *
75683 * Copyright 2018 (c) Jose Cabral, fortiss GmbH
75684 */
75685
75686#ifdef UA_ARCHITECTURE_WIN32
75687
75688
75689/* Global malloc singletons */
75690#ifdef UA_ENABLE_MALLOC_SINGLETON
75691UA_EXPORT UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size) = malloc;
75692UA_EXPORT UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr) = free;
75693UA_EXPORT UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize) = calloc;
75694UA_EXPORT UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size) = realloc;
75695#endif
75696
75697unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
75698 u_long iMode = 0;
75699 if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
75700 return UA_STATUSCODE_BADINTERNALERROR;
75701 return UA_STATUSCODE_GOOD;
75702}
75703
75704unsigned int UA_socket_set_nonblocking(UA_SOCKET sockfd){
75705 u_long iMode = 1;
75706 if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
75707 return UA_STATUSCODE_BADINTERNALERROR;
75708 return UA_STATUSCODE_GOOD;
75709}
75710
75711void UA_initialize_architecture_network(void){
75712 WSADATA wsaData;
75713 WSAStartup(MAKEWORD(2, 2), &wsaData);
75714}
75715
75716void UA_deinitialize_architecture_network(void){
75717 WSACleanup();
75718}
75719
75720#endif /* UA_ARCHITECTURE_WIN32 */
75721
75722/**** amalgamated original file "/arch/network_tcp.c" ****/
75723
75724/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75725 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75726 *
75727 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
75728 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
75729 * Copyright 2017 (c) frax2222
75730 * Copyright 2017 (c) Jose Cabral
75731 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
75732 * Copyright 2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
75733 */
75734
75735#define UA_INTERNAL
75736
75737
75738
75739#include <string.h> // memset
75740
75741#ifndef MSG_NOSIGNAL
75742#define MSG_NOSIGNAL 0
75743#endif
75744
75745/****************************/
75746/* Generic Socket Functions */
75747/****************************/
75748
75749static UA_StatusCode
75750connection_getsendbuffer(UA_Connection *connection,
75751 size_t length, UA_ByteString *buf) {
75752 UA_SecureChannel *channel = connection->channel;
75753 if(channel && channel->config.sendBufferSize < length)
75754 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
75755 return UA_ByteString_allocBuffer(bs: buf, length);
75756}
75757
75758static void
75759connection_releasesendbuffer(UA_Connection *connection,
75760 UA_ByteString *buf) {
75761 UA_ByteString_clear(p: buf);
75762}
75763
75764static void
75765connection_releaserecvbuffer(UA_Connection *connection,
75766 UA_ByteString *buf) {
75767 UA_ByteString_clear(p: buf);
75768}
75769
75770static UA_StatusCode
75771connection_write(UA_Connection *connection, UA_ByteString *buf) {
75772 if(connection->state == UA_CONNECTIONSTATE_CLOSED) {
75773 UA_ByteString_clear(p: buf);
75774 return UA_STATUSCODE_BADCONNECTIONCLOSED;
75775 }
75776
75777 /* Prevent OS signals when sending to a closed socket */
75778 int flags = 0;
75779 flags |= MSG_NOSIGNAL;
75780
75781 struct pollfd poll_fd[1];
75782 poll_fd[0].fd = connection->sockfd;
75783 poll_fd[0].events = UA_POLLOUT;
75784
75785 /* Send the full buffer. This may require several calls to send */
75786 size_t nWritten = 0;
75787 do {
75788 ssize_t n = 0;
75789 do {
75790 size_t bytes_to_send = buf->length - nWritten;
75791 n = UA_send(fd: connection->sockfd,
75792 buf: (const char*)buf->data + nWritten,
75793 n: bytes_to_send, flags: flags);
75794 if(n<0) {
75795 if(UA_ERRNO != UA_INTERRUPTED && UA_ERRNO != UA_AGAIN) {
75796 connection->close(connection);
75797 UA_ByteString_clear(p: buf);
75798 return UA_STATUSCODE_BADCONNECTIONCLOSED;
75799 }
75800 int poll_ret;
75801 do {
75802 poll_ret = UA_poll (fds: poll_fd, nfds: 1, timeout: 1000);
75803 } while (poll_ret == 0 || (poll_ret < 0 && UA_ERRNO == UA_INTERRUPTED));
75804 }
75805 } while(n < 0);
75806
75807 nWritten += (size_t)n;
75808 } while(nWritten < buf->length);
75809
75810 /* Free the buffer */
75811 UA_ByteString_clear(p: buf);
75812 return UA_STATUSCODE_GOOD;
75813}
75814
75815static UA_StatusCode
75816connection_recv(UA_Connection *connection, UA_ByteString *response,
75817 UA_UInt32 timeout) {
75818 if(connection->state == UA_CONNECTIONSTATE_CLOSED)
75819 return UA_STATUSCODE_BADCONNECTIONCLOSED;
75820
75821 /* Listen on the socket for the given timeout until a message arrives */
75822 fd_set fdset;
75823 FD_ZERO(&fdset);
75824 UA_fd_set(connection->sockfd, &fdset);
75825 UA_UInt32 timeout_usec = timeout * 1000;
75826 struct timeval tmptv = {(long int)(timeout_usec / 1000000),
75827 (int)(timeout_usec % 1000000)};
75828 int resultsize = UA_select(nfds: connection->sockfd+1, readfds: &fdset, NULL, NULL, timeout: &tmptv);
75829
75830 /* No result */
75831 if(resultsize == 0)
75832 return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
75833
75834 if(resultsize == -1) {
75835 /* The call to select was interrupted. Act as if it timed out. */
75836 if(UA_ERRNO == UA_INTERRUPTED)
75837 return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
75838
75839 /* The error cannot be recovered. Close the connection. */
75840 connection->close(connection);
75841 return UA_STATUSCODE_BADCONNECTIONCLOSED;
75842 }
75843
75844 UA_Boolean internallyAllocated = !response->length;
75845
75846 /* Allocate the buffer */
75847 if(internallyAllocated) {
75848 size_t bufferSize = 16384; /* Use as default for a new SecureChannel */
75849 UA_SecureChannel *channel = connection->channel;
75850 if(channel && channel->config.recvBufferSize > 0)
75851 bufferSize = channel->config.recvBufferSize;
75852 UA_StatusCode res = UA_ByteString_allocBuffer(bs: response, length: bufferSize);
75853 if(res != UA_STATUSCODE_GOOD)
75854 return res;
75855 }
75856
75857 /* Get the received packet(s) */
75858 ssize_t ret = UA_recv(fd: connection->sockfd, buf: (char*)response->data, n: response->length, flags: 0);
75859
75860 /* The remote side closed the connection */
75861 if(ret == 0) {
75862 if(internallyAllocated)
75863 UA_ByteString_clear(p: response);
75864 connection->close(connection);
75865 return UA_STATUSCODE_BADCONNECTIONCLOSED;
75866 }
75867
75868 /* Error case */
75869 if(ret < 0) {
75870 if(internallyAllocated)
75871 UA_ByteString_clear(p: response);
75872 if(UA_ERRNO == UA_INTERRUPTED || (timeout > 0) ?
75873 false : (UA_ERRNO == UA_EAGAIN || UA_ERRNO == UA_WOULDBLOCK))
75874 return UA_STATUSCODE_GOOD; /* statuscode_good but no data -> retry */
75875 connection->close(connection);
75876 return UA_STATUSCODE_BADCONNECTIONCLOSED;
75877 }
75878
75879 /* Set the length of the received buffer */
75880 response->length = (size_t)ret;
75881 return UA_STATUSCODE_GOOD;
75882}
75883
75884
75885/***************************/
75886/* Server NetworkLayer TCP */
75887/***************************/
75888
75889#define MAXBACKLOG 100
75890#define NOHELLOTIMEOUT 120000 /* timeout in ms before close the connection
75891 * if server does not receive Hello Message */
75892
75893typedef struct ConnectionEntry {
75894 UA_Connection connection;
75895 LIST_ENTRY(ConnectionEntry) pointers;
75896} ConnectionEntry;
75897
75898typedef struct {
75899 const UA_Logger *logger;
75900 UA_UInt16 port;
75901 UA_UInt16 maxConnections;
75902 UA_SOCKET serverSockets[FD_SETSIZE];
75903 UA_UInt16 serverSocketsSize;
75904 LIST_HEAD(, ConnectionEntry) connections;
75905 UA_UInt16 connectionsSize;
75906} ServerNetworkLayerTCP;
75907
75908static void
75909ServerNetworkLayerTCP_freeConnection(UA_Connection *connection) {
75910 UA_free(ptr: connection);
75911}
75912
75913/* This performs only 'shutdown'. 'close' is called when the shutdown
75914 * socket is returned from select. */
75915static void
75916ServerNetworkLayerTCP_close(UA_Connection *connection) {
75917 if(connection->state == UA_CONNECTIONSTATE_CLOSED)
75918 return;
75919 UA_shutdown(fd: (UA_SOCKET)connection->sockfd, how: 2);
75920 connection->state = UA_CONNECTIONSTATE_CLOSED;
75921}
75922
75923static UA_Boolean
75924purgeFirstConnectionWithoutChannel(ServerNetworkLayerTCP *layer) {
75925 ConnectionEntry *e;
75926 LIST_FOREACH(e, &layer->connections, pointers) {
75927 if(e->connection.channel == NULL) {
75928 LIST_REMOVE(e, pointers);
75929 layer->connectionsSize--;
75930 UA_close(fd: e->connection.sockfd);
75931 e->connection.free(&e->connection);
75932 return true;
75933 }
75934 }
75935 return false;
75936}
75937
75938static UA_StatusCode
75939ServerNetworkLayerTCP_add(UA_ServerNetworkLayer *nl, ServerNetworkLayerTCP *layer,
75940 UA_Int32 newsockfd, struct sockaddr_storage *remote) {
75941 if(layer->maxConnections && layer->connectionsSize >= layer->maxConnections &&
75942 !purgeFirstConnectionWithoutChannel(layer)) {
75943 return UA_STATUSCODE_BADTCPNOTENOUGHRESOURCES;
75944 }
75945
75946 /* Set nonblocking */
75947 UA_socket_set_nonblocking(sockfd: newsockfd);//TODO: check return value
75948
75949 /* Do not merge packets on the socket (disable Nagle's algorithm) */
75950 int dummy = 1;
75951 if(UA_setsockopt(fd: newsockfd, IPPROTO_TCP, TCP_NODELAY,
75952 optval: (const char *)&dummy, optlen: sizeof(dummy)) < 0) {
75953 UA_LOG_SOCKET_ERRNO_WRAP(
75954 UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK,
75955 "Cannot set socket option TCP_NODELAY. Error: %s",
75956 errno_str));
75957 return UA_STATUSCODE_BADUNEXPECTEDERROR;
75958 }
75959
75960#if defined(UA_getnameinfo)
75961 /* Get the peer name for logging */
75962 char remote_name[100];
75963 int res = UA_getnameinfo((struct sockaddr*)remote,
75964 sizeof(struct sockaddr_storage),
75965 remote_name, sizeof(remote_name),
75966 NULL, 0, NI_NUMERICHOST);
75967 if(res == 0) {
75968 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
75969 msg: "Connection %i | New connection over TCP from %s",
75970 (int)newsockfd, remote_name);
75971 } else {
75972 UA_LOG_SOCKET_ERRNO_WRAP(UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
75973 "Connection %i | New connection over TCP, "
75974 "getnameinfo failed with error: %s",
75975 (int)newsockfd, errno_str));
75976 }
75977#else
75978 UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
75979 "Connection %i | New connection over TCP",
75980 (int)newsockfd);
75981#endif
75982 /* Allocate and initialize the connection */
75983 ConnectionEntry *e = (ConnectionEntry*)UA_malloc(size: sizeof(ConnectionEntry));
75984 if(!e) {
75985 return UA_STATUSCODE_BADOUTOFMEMORY;
75986 }
75987
75988 UA_Connection *c = &e->connection;
75989 memset(s: c, c: 0, n: sizeof(UA_Connection));
75990 c->sockfd = newsockfd;
75991 c->handle = layer;
75992 c->send = connection_write;
75993 c->close = ServerNetworkLayerTCP_close;
75994 c->free = ServerNetworkLayerTCP_freeConnection;
75995 c->getSendBuffer = connection_getsendbuffer;
75996 c->releaseSendBuffer = connection_releasesendbuffer;
75997 c->releaseRecvBuffer = connection_releaserecvbuffer;
75998 c->state = UA_CONNECTIONSTATE_OPENING;
75999 c->openingDate = UA_DateTime_nowMonotonic();
76000
76001 layer->connectionsSize++;
76002
76003 /* Add to the linked list */
76004 LIST_INSERT_HEAD(&layer->connections, e, pointers);
76005 if(nl->statistics) {
76006 nl->statistics->currentConnectionCount++;
76007 nl->statistics->cumulatedConnectionCount++;
76008 }
76009 return UA_STATUSCODE_GOOD;
76010}
76011
76012static UA_StatusCode
76013addServerSocket(ServerNetworkLayerTCP *layer, struct addrinfo *ai) {
76014 /* Create the server socket */
76015 UA_SOCKET newsock = UA_socket(domain: ai->ai_family, type: ai->ai_socktype, protocol: ai->ai_protocol);
76016 if(newsock == UA_INVALID_SOCKET)
76017 {
76018 UA_LOG_SOCKET_ERRNO_WRAP(
76019 UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76020 "Error opening the server socket: %s", errno_str));
76021 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76022 }
76023
76024 /* Some Linux distributions have net.ipv6.bindv6only not activated. So
76025 * sockets can double-bind to IPv4 and IPv6. This leads to problems. Use
76026 * AF_INET6 sockets only for IPv6. */
76027
76028 int optval = 1;
76029#if UA_IPV6
76030 if(ai->ai_family == AF_INET6 &&
76031 UA_setsockopt(fd: newsock, IPPROTO_IPV6, IPV6_V6ONLY,
76032 optval: (const char*)&optval, optlen: sizeof(optval)) == -1) {
76033 UA_LOG_WARNING(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76034 msg: "Could not set an IPv6 socket to IPv6 only");
76035 UA_close(fd: newsock);
76036 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76037
76038 }
76039#endif
76040 if(UA_setsockopt(fd: newsock, SOL_SOCKET, SO_REUSEADDR,
76041 optval: (const char *)&optval, optlen: sizeof(optval)) == -1) {
76042 UA_LOG_WARNING(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76043 msg: "Could not make the socket reusable");
76044 UA_close(fd: newsock);
76045 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76046 }
76047
76048
76049 if(UA_socket_set_nonblocking(sockfd: newsock) != UA_STATUSCODE_GOOD) {
76050 UA_LOG_WARNING(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76051 msg: "Could not set the server socket to nonblocking");
76052 UA_close(fd: newsock);
76053 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76054 }
76055
76056 /* Bind socket to address */
76057 int ret = UA_bind(fd: newsock, addr: ai->ai_addr, len: (socklen_t)ai->ai_addrlen);
76058 if(ret < 0) {
76059 /* If bind to specific address failed, try to bind *-socket */
76060 if(ai->ai_family == AF_INET) {
76061 struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
76062 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
76063 sin->sin_addr.s_addr = 0;
76064 ret = 0;
76065 }
76066 }
76067#if UA_IPV6
76068 else if(ai->ai_family == AF_INET6) {
76069 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
76070 if(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
76071 memset(s: &sin6->sin6_addr, c: 0, n: sizeof(sin6->sin6_addr));
76072 sin6->sin6_scope_id = 0;
76073 ret = 0;
76074 }
76075 }
76076#endif // UA_IPV6
76077 if(ret == 0) {
76078 ret = UA_bind(fd: newsock, addr: ai->ai_addr, len: (socklen_t)ai->ai_addrlen);
76079 if(ret == 0) {
76080 /* The second bind fixed the issue, inform the user. */
76081 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76082 msg: "Server socket bound to unspecified address");
76083 }
76084 }
76085 }
76086 if(ret < 0) {
76087 UA_LOG_SOCKET_ERRNO_WRAP(
76088 UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76089 "Error binding a server socket: %s", errno_str));
76090 UA_close(fd: newsock);
76091 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76092 }
76093
76094 /* Start listening */
76095 if(UA_listen(fd: newsock, MAXBACKLOG) < 0) {
76096 UA_LOG_SOCKET_ERRNO_WRAP(
76097 UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76098 "Error listening on server socket: %s", errno_str));
76099 UA_close(fd: newsock);
76100 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76101 }
76102
76103 if(layer->port == 0) {
76104 /* Port was automatically chosen. Read it from the OS */
76105 struct sockaddr_in returned_addr;
76106 memset(s: &returned_addr, c: 0, n: sizeof(returned_addr));
76107 socklen_t len = sizeof(returned_addr);
76108 UA_getsockname(fd: newsock, addr: (struct sockaddr *)&returned_addr, len: &len);
76109 layer->port = ntohs(netshort: returned_addr.sin_port);
76110 }
76111
76112 layer->serverSockets[layer->serverSocketsSize] = newsock;
76113 layer->serverSocketsSize++;
76114 return UA_STATUSCODE_GOOD;
76115}
76116
76117static UA_StatusCode
76118ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, const UA_Logger *logger,
76119 const UA_String *customHostname) {
76120 UA_initialize_architecture_network();
76121
76122 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
76123 layer->logger = logger;
76124
76125 /* Get addrinfo of the server and create server sockets */
76126 char hostname[512];
76127 if(customHostname->length) {
76128 if(customHostname->length >= sizeof(hostname))
76129 return UA_STATUSCODE_BADOUTOFMEMORY;
76130 memcpy(dest: hostname, src: customHostname->data, n: customHostname->length);
76131 hostname[customHostname->length] = '\0';
76132 }
76133 char portno[6];
76134 UA_snprintf(s: portno, maxlen: 6, format: "%d", layer->port);
76135 struct addrinfo hints, *res;
76136 memset(s: &hints, c: 0, n: sizeof hints);
76137#if UA_IPV6
76138 hints.ai_family = AF_UNSPEC; /* allow IPv4 and IPv6 */
76139#else
76140 hints.ai_family = AF_INET; /* enforce IPv4 only */
76141#endif
76142 hints.ai_socktype = SOCK_STREAM;
76143 hints.ai_flags = AI_PASSIVE;
76144#ifdef AI_ADDRCONFIG
76145 hints.ai_flags |= AI_ADDRCONFIG;
76146#endif
76147 hints.ai_protocol = IPPROTO_TCP;
76148 int retcode = UA_getaddrinfo(name: customHostname->length ? hostname : NULL,
76149 service: portno, req: &hints, pai: &res);
76150 if(retcode != 0) {
76151 UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76152 "getaddrinfo lookup of %s failed with error %d - %s", hostname, retcode, errno_str));
76153 return UA_STATUSCODE_BADINTERNALERROR;
76154 }
76155
76156 /* There might be serveral addrinfos (for different network cards,
76157 * IPv4/IPv6). Add a server socket for all of them. */
76158 struct addrinfo *ai = res;
76159 for(layer->serverSocketsSize = 0;
76160 layer->serverSocketsSize < FD_SETSIZE && ai != NULL;
76161 ai = ai->ai_next) {
76162 addServerSocket(layer, ai);
76163 }
76164 UA_freeaddrinfo(ai: res);
76165
76166 if(layer->serverSocketsSize == 0) {
76167 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76168 }
76169
76170 /* Get the discovery url from the hostname */
76171 UA_String du = UA_STRING_NULL;
76172 char discoveryUrlBuffer[256];
76173 if(customHostname->length) {
76174 du.length = (size_t)UA_snprintf(s: discoveryUrlBuffer, maxlen: 255, format: "opc.tcp://%.*s:%d/",
76175 (int)customHostname->length, customHostname->data,
76176 layer->port);
76177 du.data = (UA_Byte*)discoveryUrlBuffer;
76178 } else {
76179 char hostnameBuffer[256];
76180 if(UA_gethostname(name: hostnameBuffer, len: 255) == 0) {
76181 du.length = (size_t)UA_snprintf(s: discoveryUrlBuffer, maxlen: 255, format: "opc.tcp://%s:%d/",
76182 hostnameBuffer, layer->port);
76183 du.data = (UA_Byte*)discoveryUrlBuffer;
76184 } else {
76185 UA_LOG_ERROR(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK, msg: "Could not get the hostname");
76186 return UA_STATUSCODE_BADINTERNALERROR;
76187 }
76188 }
76189 UA_String_copy(src: &du, dst: &nl->discoveryUrl);
76190
76191 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76192 msg: "TCP network layer listening on %.*s",
76193 (int)nl->discoveryUrl.length, nl->discoveryUrl.data);
76194 return UA_STATUSCODE_GOOD;
76195}
76196
76197/* After every select, reset the sockets to listen on */
76198static UA_Int32
76199setFDSet(ServerNetworkLayerTCP *layer, fd_set *fdset) {
76200 FD_ZERO(fdset);
76201 UA_Int32 highestfd = 0;
76202 for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
76203 UA_fd_set(layer->serverSockets[i], fdset);
76204 if((UA_Int32)layer->serverSockets[i] > highestfd)
76205 highestfd = (UA_Int32)layer->serverSockets[i];
76206 }
76207
76208 ConnectionEntry *e;
76209 LIST_FOREACH(e, &layer->connections, pointers) {
76210 UA_fd_set(e->connection.sockfd, fdset);
76211 if((UA_Int32)e->connection.sockfd > highestfd)
76212 highestfd = (UA_Int32)e->connection.sockfd;
76213 }
76214
76215 return highestfd;
76216}
76217
76218static UA_StatusCode
76219ServerNetworkLayerTCP_listen(UA_ServerNetworkLayer *nl, UA_Server *server,
76220 UA_UInt16 timeout) {
76221 /* Every open socket can generate two jobs */
76222 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
76223
76224 if(layer->serverSocketsSize == 0)
76225 return UA_STATUSCODE_GOOD;
76226
76227 /* Listen on open sockets (including the server) */
76228 fd_set fdset, errset;
76229 UA_Int32 highestfd = setFDSet(layer, fdset: &fdset);
76230 setFDSet(layer, fdset: &errset);
76231 struct timeval tmptv = {0, timeout * 1000};
76232 if(UA_select(nfds: highestfd+1, readfds: &fdset, NULL, exceptfds: &errset, timeout: &tmptv) < 0) {
76233 UA_LOG_SOCKET_ERRNO_WRAP(
76234 UA_LOG_DEBUG(layer->logger, UA_LOGCATEGORY_NETWORK,
76235 "Socket select failed with %s", errno_str));
76236 // we will retry, so do not return bad
76237 return UA_STATUSCODE_GOOD;
76238 }
76239
76240 /* Accept new connections via the server sockets */
76241 for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
76242 if(!UA_fd_isset(layer->serverSockets[i], &fdset))
76243 continue;
76244
76245 struct sockaddr_storage remote;
76246 socklen_t remote_size = sizeof(remote);
76247 UA_SOCKET newsockfd = UA_accept(fd: layer->serverSockets[i],
76248 addr: (struct sockaddr*)&remote, addr_len: &remote_size);
76249 if(newsockfd == UA_INVALID_SOCKET)
76250 continue;
76251
76252 UA_LOG_TRACE(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76253 msg: "Connection %i | New TCP connection on server socket %i",
76254 (int)newsockfd, (int)(layer->serverSockets[i]));
76255
76256 if(ServerNetworkLayerTCP_add(nl, layer, newsockfd: (UA_Int32)newsockfd, remote: &remote) != UA_STATUSCODE_GOOD) {
76257 UA_close(fd: newsockfd);
76258 }
76259 }
76260
76261 /* Read from established sockets */
76262 ConnectionEntry *e, *e_tmp;
76263 UA_DateTime now = UA_DateTime_nowMonotonic();
76264 LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
76265 if((e->connection.state == UA_CONNECTIONSTATE_OPENING) &&
76266 (now > (e->connection.openingDate + (NOHELLOTIMEOUT * UA_DATETIME_MSEC)))) {
76267 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76268 msg: "Connection %i | Closed by the server (no Hello Message)",
76269 (int)(e->connection.sockfd));
76270 LIST_REMOVE(e, pointers);
76271 layer->connectionsSize--;
76272 UA_close(fd: e->connection.sockfd);
76273 UA_Server_removeConnection(server, connection: &e->connection);
76274 if(nl->statistics) {
76275 nl->statistics->connectionTimeoutCount++;
76276 nl->statistics->currentConnectionCount--;
76277 }
76278 continue;
76279 }
76280
76281 if(!UA_fd_isset(e->connection.sockfd, &errset) &&
76282 !UA_fd_isset(e->connection.sockfd, &fdset))
76283 continue;
76284
76285 UA_LOG_TRACE(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76286 msg: "Connection %i | Activity on the socket",
76287 (int)(e->connection.sockfd));
76288
76289 UA_ByteString buf = UA_BYTESTRING_NULL;
76290 UA_StatusCode retval = connection_recv(connection: &e->connection, response: &buf, timeout: 0);
76291
76292 if(retval == UA_STATUSCODE_GOOD) {
76293 /* Process packets */
76294 UA_Server_processBinaryMessage(server, connection: &e->connection, message: &buf);
76295 connection_releaserecvbuffer(connection: &e->connection, buf: &buf);
76296 } else if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
76297 /* The socket is shutdown but not closed */
76298 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76299 msg: "Connection %i | Closed",
76300 (int)(e->connection.sockfd));
76301 LIST_REMOVE(e, pointers);
76302 layer->connectionsSize--;
76303 UA_close(fd: e->connection.sockfd);
76304 UA_Server_removeConnection(server, connection: &e->connection);
76305 if(nl->statistics) {
76306 nl->statistics->currentConnectionCount--;
76307 }
76308 }
76309 }
76310 return UA_STATUSCODE_GOOD;
76311}
76312
76313static void
76314ServerNetworkLayerTCP_stop(UA_ServerNetworkLayer *nl, UA_Server *server) {
76315 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
76316 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76317 msg: "Shutting down the TCP network layer");
76318
76319 /* Close the server sockets */
76320 for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
76321 UA_shutdown(fd: layer->serverSockets[i], how: 2);
76322 UA_close(fd: layer->serverSockets[i]);
76323 }
76324 layer->serverSocketsSize = 0;
76325
76326 /* Close open connections */
76327 ConnectionEntry *e;
76328 LIST_FOREACH(e, &layer->connections, pointers)
76329 ServerNetworkLayerTCP_close(connection: &e->connection);
76330
76331 /* Run recv on client sockets. This picks up the closed sockets and frees
76332 * the connection. */
76333 ServerNetworkLayerTCP_listen(nl, server, timeout: 0);
76334
76335 UA_deinitialize_architecture_network();
76336}
76337
76338/* run only when the server is stopped */
76339static void
76340ServerNetworkLayerTCP_clear(UA_ServerNetworkLayer *nl) {
76341 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
76342 UA_String_clear(p: &nl->discoveryUrl);
76343
76344 /* Hard-close and remove remaining connections. The server is no longer
76345 * running. So this is safe. */
76346 ConnectionEntry *e, *e_tmp;
76347 LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
76348 LIST_REMOVE(e, pointers);
76349 layer->connectionsSize--;
76350 UA_close(fd: e->connection.sockfd);
76351 UA_free(ptr: e);
76352 if(nl->statistics) {
76353 nl->statistics->currentConnectionCount--;
76354 }
76355 }
76356
76357 /* Free the layer */
76358 UA_free(ptr: layer);
76359}
76360
76361UA_ServerNetworkLayer
76362UA_ServerNetworkLayerTCP(UA_ConnectionConfig config, UA_UInt16 port,
76363 UA_UInt16 maxConnections) {
76364 UA_ServerNetworkLayer nl;
76365 memset(s: &nl, c: 0, n: sizeof(UA_ServerNetworkLayer));
76366 nl.clear = ServerNetworkLayerTCP_clear;
76367 nl.localConnectionConfig = config;
76368 nl.start = ServerNetworkLayerTCP_start;
76369 nl.listen = ServerNetworkLayerTCP_listen;
76370 nl.stop = ServerNetworkLayerTCP_stop;
76371 nl.handle = NULL;
76372
76373 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP*)
76374 UA_calloc(nmemb: 1,size: sizeof(ServerNetworkLayerTCP));
76375 if(!layer)
76376 return nl;
76377 nl.handle = layer;
76378
76379 layer->port = port;
76380 layer->maxConnections = maxConnections;
76381
76382 return nl;
76383}
76384
76385typedef struct TCPClientConnection {
76386 struct addrinfo hints, *server;
76387 UA_DateTime connStart;
76388 UA_String endpointUrl;
76389 UA_UInt32 timeout;
76390} TCPClientConnection;
76391
76392/***************************/
76393/* Client NetworkLayer TCP */
76394/***************************/
76395
76396static void
76397ClientNetworkLayerTCP_close(UA_Connection *connection) {
76398 if(connection->state == UA_CONNECTIONSTATE_CLOSED)
76399 return;
76400
76401 if(connection->sockfd != UA_INVALID_SOCKET) {
76402 UA_shutdown(fd: connection->sockfd, how: 2);
76403 UA_close(fd: connection->sockfd);
76404 }
76405 connection->state = UA_CONNECTIONSTATE_CLOSED;
76406}
76407
76408static void
76409ClientNetworkLayerTCP_free(UA_Connection *connection) {
76410 if(!connection->handle)
76411 return;
76412
76413 TCPClientConnection *tcpConnection = (TCPClientConnection *)connection->handle;
76414 if(tcpConnection->server)
76415 UA_freeaddrinfo(ai: tcpConnection->server);
76416 UA_String_clear(p: &tcpConnection->endpointUrl);
76417 UA_free(ptr: tcpConnection);
76418 connection->handle = NULL;
76419}
76420
76421UA_StatusCode
76422UA_ClientConnectionTCP_poll(UA_Connection *connection, UA_UInt32 timeout,
76423 const UA_Logger *logger) {
76424 if(connection->state == UA_CONNECTIONSTATE_CLOSED)
76425 return UA_STATUSCODE_BADDISCONNECT;
76426 if(connection->state == UA_CONNECTIONSTATE_ESTABLISHED)
76427 return UA_STATUSCODE_GOOD;
76428
76429 /* Connection timeout? */
76430 TCPClientConnection *tcpConnection = (TCPClientConnection*) connection->handle;
76431 if(tcpConnection == NULL) {
76432 connection->state = UA_CONNECTIONSTATE_CLOSED;
76433 return UA_STATUSCODE_BADDISCONNECT; // some thing is wrong
76434 }
76435 if((UA_Double) (UA_DateTime_nowMonotonic() - tcpConnection->connStart)
76436 > (UA_Double) tcpConnection->timeout * UA_DATETIME_MSEC ) {
76437 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK, msg: "Timed out");
76438 ClientNetworkLayerTCP_close(connection);
76439 return UA_STATUSCODE_BADDISCONNECT;
76440 }
76441
76442 /* Get a socket and connect (only once) if not already done in a previous
76443 * call. On win32, calling connect multiple times is not recommended on
76444 * non-blocking sockets
76445 * (https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect).
76446 * On posix it is also not necessary to call connect multiple times.
76447 *
76448 * Identification of successfull connection is done using select (writeable/errorfd)
76449 * and getsockopt using SO_ERROR on win32 and posix.
76450 */
76451 if(connection->sockfd == UA_INVALID_SOCKET) {
76452 connection->sockfd = UA_socket(domain: tcpConnection->server->ai_family,
76453 type: tcpConnection->server->ai_socktype,
76454 protocol: tcpConnection->server->ai_protocol);
76455 if(connection->sockfd == UA_INVALID_SOCKET) {
76456 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76457 msg: "Could not create client socket: %s", strerror(UA_ERRNO));
76458 ClientNetworkLayerTCP_close(connection);
76459 return UA_STATUSCODE_BADDISCONNECT;
76460 }
76461
76462 /* Non blocking connect to be able to timeout */
76463 if(UA_socket_set_nonblocking(sockfd: connection->sockfd) != UA_STATUSCODE_GOOD) {
76464 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76465 msg: "Could not set the client socket to nonblocking");
76466 ClientNetworkLayerTCP_close(connection);
76467 return UA_STATUSCODE_BADDISCONNECT;
76468 }
76469
76470 /* Don't have the socket create interrupt signals */
76471#ifdef SO_NOSIGPIPE
76472 int val = 1;
76473 int sso_result = setsockopt(connection->sockfd, SOL_SOCKET, SO_NOSIGPIPE,
76474 (void *)&val, sizeof(val));
76475 if(sso_result < 0)
76476 UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, "Couldn't set SO_NOSIGPIPE");
76477#endif
76478 int error = UA_connect(fd: connection->sockfd, addr: tcpConnection->server->ai_addr,
76479 len: tcpConnection->server->ai_addrlen);
76480
76481 /* Connection successful */
76482 if(error == 0) {
76483 connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
76484 return UA_STATUSCODE_GOOD;
76485 }
76486
76487 /* The connection failed */
76488 if((UA_ERRNO != UA_ERR_CONNECTION_PROGRESS)) {
76489 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76490 msg: "Connection to %.*s failed with error: %s",
76491 (int)tcpConnection->endpointUrl.length,
76492 tcpConnection->endpointUrl.data, strerror(UA_ERRNO));
76493 ClientNetworkLayerTCP_close(connection);
76494 return UA_STATUSCODE_BADDISCONNECT;
76495 }
76496 }
76497
76498 /* Use select to wait until connected. Return with a half-opened connection
76499 * after a timeout. */
76500 UA_UInt32 timeout_usec = timeout * 1000;
76501
76502#ifdef _OS9000
76503 /* OS-9 cannot use select for checking write sockets. Therefore, we need to
76504 * use connect until success or failed */
76505 int resultsize = 0;
76506 do {
76507 u_int32 time = 0x80000001;
76508 signal_code sig;
76509
76510 timeout_usec -= 1000000/256; // Sleep 1/256 second
76511 if(timeout_usec < 0)
76512 break;
76513
76514 _os_sleep(&time, &sig);
76515 error = connect(connection->sockfd, tcpConnection->server->ai_addr,
76516 tcpConnection->server->ai_addrlen);
76517 if((error == -1 && UA_ERRNO == EISCONN) || (error == 0))
76518 resultsize = 1;
76519 if(error == -1 && UA_ERRNO != EALREADY && UA_ERRNO != EINPROGRESS)
76520 break;
76521 } while(resultsize == 0);
76522#else
76523 /* Wait in a select-call until the connection fully opens or the timeout
76524 * happens */
76525
76526 /* On windows select both writing and error fdset */
76527 fd_set writing_fdset;
76528 FD_ZERO(&writing_fdset);
76529 UA_fd_set(connection->sockfd, &writing_fdset);
76530 fd_set error_fdset;
76531 FD_ZERO(&error_fdset);
76532#ifdef _WIN32
76533 UA_fd_set(connection->sockfd, &error_fdset);
76534#endif
76535 struct timeval tmptv = {(long int)(timeout_usec / 1000000),
76536 (int)(timeout_usec % 1000000)};
76537
76538 int ret = UA_select(nfds: (UA_Int32)(connection->sockfd + 1), NULL, writefds: &writing_fdset,
76539 exceptfds: &error_fdset, timeout: &tmptv);
76540
76541 // When select fails abort connection
76542 if(ret == -1) {
76543 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76544 msg: "Connection to %.*s failed with error: %s",
76545 (int)tcpConnection->endpointUrl.length,
76546 tcpConnection->endpointUrl.data, strerror(UA_ERRNO));
76547 ClientNetworkLayerTCP_close(connection);
76548 return UA_STATUSCODE_BADDISCONNECT;
76549 } else if (timeout && ret == 0) {
76550 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76551 msg: "Connection to %.*s timed out",
76552 (int)tcpConnection->endpointUrl.length,
76553 tcpConnection->endpointUrl.data);
76554 ClientNetworkLayerTCP_close(connection);
76555 return UA_STATUSCODE_BADTIMEOUT;
76556 }
76557
76558 int resultsize = UA_fd_isset(connection->sockfd, &writing_fdset);
76559#endif
76560
76561 /* Any errors on the socket reported? */
76562 OPTVAL_TYPE so_error = 0;
76563 socklen_t len = sizeof(so_error);
76564 ret = UA_getsockopt(fd: connection->sockfd, SOL_SOCKET, SO_ERROR, optval: &so_error, optlen: &len);
76565 if(ret != 0 || so_error != 0) {
76566 // no UA_LOG_SOCKET_ERRNO_GAI_WRAP because of so_error
76567#ifndef _WIN32
76568 char *errno_str = strerror(errnum: ret == 0 ? so_error : UA_ERRNO);
76569#elif defined(UNDER_CE)
76570 LPVOID errno_str = NULL;
76571 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
76572 FORMAT_MESSAGE_IGNORE_INSERTS,
76573 NULL, ret == 0 ? so_error : WSAGetLastError(),
76574 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&errno_str, 0,
76575 NULL);
76576#else
76577 char *errno_str = NULL;
76578 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
76579 FORMAT_MESSAGE_IGNORE_INSERTS,
76580 NULL, ret == 0 ? so_error : WSAGetLastError(),
76581 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&errno_str, 0,
76582 NULL);
76583#endif
76584 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76585 msg: "Connection to %.*s failed with error: %s",
76586 (int)tcpConnection->endpointUrl.length,
76587 tcpConnection->endpointUrl.data, errno_str);
76588#ifdef _WIN32
76589 LocalFree(errno_str);
76590#endif
76591 ClientNetworkLayerTCP_close(connection);
76592 return UA_STATUSCODE_BADDISCONNECT;
76593 }
76594
76595 /* The connection is fully opened. Otherwise, select has timed out. But we
76596 * can retry. */
76597 if(resultsize > 0)
76598 connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
76599
76600 return UA_STATUSCODE_GOOD;
76601}
76602
76603UA_Connection
76604UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpointUrl,
76605 UA_UInt32 timeout, const UA_Logger *logger) {
76606 UA_initialize_architecture_network();
76607
76608 UA_Connection connection;
76609 memset(s: &connection, c: 0, n: sizeof(UA_Connection));
76610
76611 connection.state = UA_CONNECTIONSTATE_OPENING;
76612 connection.sockfd = UA_INVALID_SOCKET;
76613 connection.send = connection_write;
76614 connection.recv = connection_recv;
76615 connection.close = ClientNetworkLayerTCP_close;
76616 connection.free = ClientNetworkLayerTCP_free;
76617 connection.getSendBuffer = connection_getsendbuffer;
76618 connection.releaseSendBuffer = connection_releasesendbuffer;
76619 connection.releaseRecvBuffer = connection_releaserecvbuffer;
76620
76621 TCPClientConnection *tcpClientConnection = (TCPClientConnection*)
76622 UA_malloc(size: sizeof(TCPClientConnection));
76623 if(!tcpClientConnection) {
76624 connection.state = UA_CONNECTIONSTATE_CLOSED;
76625 return connection;
76626 }
76627 memset(s: tcpClientConnection, c: 0, n: sizeof(TCPClientConnection));
76628 connection.handle = (void*) tcpClientConnection;
76629 tcpClientConnection->timeout = timeout;
76630 UA_String hostnameString = UA_STRING_NULL;
76631 UA_String pathString = UA_STRING_NULL;
76632 UA_UInt16 port = 0;
76633 char hostname[512];
76634 tcpClientConnection->connStart = UA_DateTime_nowMonotonic();
76635 UA_String_copy(src: &endpointUrl, dst: &tcpClientConnection->endpointUrl);
76636
76637 UA_StatusCode parse_retval =
76638 UA_parseEndpointUrl(endpointUrl: &endpointUrl, outHostname: &hostnameString, outPort: &port, outPath: &pathString);
76639 if(parse_retval != UA_STATUSCODE_GOOD || hostnameString.length > 511) {
76640 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76641 msg: "Server url is invalid: %.*s",
76642 (int)endpointUrl.length, endpointUrl.data);
76643 connection.state = UA_CONNECTIONSTATE_CLOSED;
76644 return connection;
76645 }
76646 memcpy(dest: hostname, src: hostnameString.data, n: hostnameString.length);
76647 hostname[hostnameString.length] = 0;
76648
76649 if(port == 0) {
76650 port = 4840;
76651 UA_LOG_INFO(logger, category: UA_LOGCATEGORY_NETWORK,
76652 msg: "No port defined, using default port %" PRIu16, port);
76653 }
76654
76655 memset(s: &tcpClientConnection->hints, c: 0, n: sizeof(tcpClientConnection->hints));
76656 tcpClientConnection->hints.ai_family = AF_UNSPEC;
76657 tcpClientConnection->hints.ai_socktype = SOCK_STREAM;
76658 char portStr[6];
76659 UA_snprintf(s: portStr, maxlen: 6, format: "%d", port);
76660 int error = UA_getaddrinfo(name: hostname, service: portStr, req: &tcpClientConnection->hints,
76661 pai: &tcpClientConnection->server);
76662 if(error != 0 || !tcpClientConnection->server) {
76663 UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
76664 "DNS lookup of %s failed with error %d - %s",
76665 hostname, error, errno_str));
76666 connection.state = UA_CONNECTIONSTATE_CLOSED;
76667 return connection;
76668 }
76669
76670 /* Return connection with state UA_CONNECTIONSTATE_OPENING */
76671 return connection;
76672}
76673

source code of qtopcua/src/3rdparty/open62541/open62541.c